Attachment 'mri.c'

Download

   1 /*
   2  *       FILE NAME:   mri.c
   3  *
   4  *       DESCRIPTION: utilities for MRI  data structure
   5  *
   6  *       AUTHOR:      Bruce Fischl
   7  *       DATE:        1/8/97
   8  *
   9  */
  10 // Warning: Do not edit the following four lines.  CVS maintains them.
  11 // Revision Author: $Author: nicks $
  12 // Revision Date  : $Date: 2006/01/17 22:16:34 $
  13 // Revision       : $Revision: 1.325 $
  14 char *MRI_C_VERSION = "$Revision: 1.325 $";
  15 
  16 /*-----------------------------------------------------
  17   INCLUDE FILES
  18   -------------------------------------------------------*/
  19 #define USE_ELECTRIC_FENCE  1
  20 
  21 #include <stdio.h>
  22 #include <stdlib.h>
  23 #include <math.h>
  24 #include <string.h>
  25 #include <memory.h>
  26 #include <errno.h>
  27 #include <ctype.h>
  28 #include "error.h"
  29 #include "proto.h"
  30 #include "mri.h"
  31 #include "macros.h"
  32 #include "diag.h"
  33 #include "volume_io.h"
  34 #include "filter.h"
  35 #include "box.h"
  36 #include "region.h"
  37 #include "mri_transform.h"
  38 #include "utils.h"
  39 #include "matrix.h"
  40 #include "pdf.h"
  41 #include "cma.h"
  42 #include "talairachex.h"
  43 #include "voxlist.h"
  44 
  45 extern int errno;
  46 
  47 /*-----------------------------------------------------
  48   MACROS AND CONSTANTS
  49   -------------------------------------------------------*/
  50 
  51 #define DEBUG_POINT(x,y,z)  (((x==8&&y==9) || (x==9&&y==8)) &&((z)==15))
  52 
  53 /*-----------------------------------------------------
  54   STATIC DATA
  55   -------------------------------------------------------*/
  56 
  57 static long mris_alloced = 0 ;
  58 
  59 /*-----------------------------------------------------
  60   STATIC PROTOTYPES
  61   -------------------------------------------------------*/
  62 
  63 /*-----------------------------------------------------
  64   GLOBAL FUNCTIONS
  65   -------------------------------------------------------*/
  66 
  67 /*----------------------------------------------------------
  68   MRIxfmCRS2XYZ() - computes the matrix needed to compute the
  69   XYZ of the center of a voxel at a given Col, Row, and Slice
  70   from the native geometry of the volume
  71 
  72   x         col
  73   y  = T *  row
  74   z        slice
  75   1          1
  76 
  77   T = [Mdc*D Pxyz0]
  78   [0 0 0   1  ]
  79 
  80   Mdc = [Vcol Vrow Vslice]
  81   V<dim> = the direction cosine pointing from the center of one voxel
  82   to the center of an adjacent voxel in the next dim, where
  83   dim is either colum, row, or slice. Vcol = [x_r x_a x_s],
  84   Vrow = [y_r y_a y_s], Vslice = [z_r z_a z_s]. Vcol can also
  85   be described as the vector normal to the plane formed by
  86   the rows and slices of a given column (ie, the column normal).
  87 
  88   D = diag([colres rowres sliceres])
  89   dimres = the distance between adjacent dim, where colres = mri->xsize,
  90   rowres = mri->ysize, and sliceres = mri->zsize.
  91 
  92   Pxyz0 = the XYZ location at CRS=0. This number is not part of the
  93   mri structure, so it is computed here according to the formula:
  94   Pxyz0 = PxyzCenter - Mdc*D*PcrsCenter
  95 
  96   PcrsCenter = the col, row, and slice at the center of the volume,
  97   = [ ncols/2 nrows/2 nslices/2 ]
  98 
  99   PxyzCenter = the X, Y, and Z at the center of the volume and does
 100   exist in the header as mri->c_r, mri->c_a, and mri->c_s,
 101   respectively.
 102 
 103   Note: to compute the matrix with respect to the first voxel being
 104   at CRS 1,1,1 instead of 0,0,0, then set base = 1. This is
 105   necessary with SPM matrices.
 106 
 107   See also: MRIxfmCRS2XYZtkreg, MRItkReg2Native
 108   ------------------------------------------------------*/
 109 MATRIX *MRIxfmCRS2XYZ(MRI *mri, int base)
 110 {
 111   MATRIX *m;
 112   MATRIX *Pcrs, *PxyzOffset;
 113 
 114   m = MatrixAlloc(4, 4, MATRIX_REAL);
 115 
 116   /* direction cosine between columns scaled by
 117      distance between colums */
 118   *MATRIX_RELT(m, 1, 1) = mri->x_r * mri->xsize;
 119   *MATRIX_RELT(m, 2, 1) = mri->x_a * mri->xsize;
 120   *MATRIX_RELT(m, 3, 1) = mri->x_s * mri->xsize;
 121 
 122   /* direction cosine between rows scaled by
 123      distance between rows */
 124   *MATRIX_RELT(m, 1, 2) = mri->y_r * mri->ysize;
 125   *MATRIX_RELT(m, 2, 2) = mri->y_a * mri->ysize;
 126   *MATRIX_RELT(m, 3, 2) = mri->y_s * mri->ysize;
 127 
 128   /* direction cosine between slices scaled by
 129      distance between slices */
 130   *MATRIX_RELT(m, 1, 3) = mri->z_r * mri->zsize;
 131   *MATRIX_RELT(m, 2, 3) = mri->z_a * mri->zsize;
 132   *MATRIX_RELT(m, 3, 3) = mri->z_s * mri->zsize;
 133 
 134   /* Preset the offsets to 0 */
 135   *MATRIX_RELT(m, 1, 4) = 0.0;
 136   *MATRIX_RELT(m, 2, 4) = 0.0;
 137   *MATRIX_RELT(m, 3, 4) = 0.0;
 138 
 139   /* Last row of matrix */
 140   *MATRIX_RELT(m, 4, 1) = 0.0;
 141   *MATRIX_RELT(m, 4, 2) = 0.0;
 142   *MATRIX_RELT(m, 4, 3) = 0.0;
 143   *MATRIX_RELT(m, 4, 4) = 1.0;
 144 
 145   /* At this point, m = Mdc * D */
 146 
 147   /* Col, Row, Slice at the Center of the Volume */
 148   Pcrs = MatrixAlloc(4, 1, MATRIX_REAL);
 149   *MATRIX_RELT(Pcrs, 1, 1) = mri->width/2.0  + base;
 150   *MATRIX_RELT(Pcrs, 2, 1) = mri->height/2.0 + base;
 151   *MATRIX_RELT(Pcrs, 3, 1) = mri->depth/2.0  + base;
 152   *MATRIX_RELT(Pcrs, 4, 1) = 1.0;
 153 
 154   /* XYZ offset the first Col, Row, and Slice from Center */
 155   /* PxyzOffset = Mdc*D*PcrsCenter */
 156   PxyzOffset = MatrixMultiply(m,Pcrs,NULL);
 157 
 158   /* XYZ at the Center of the Volume is mri->c_r, c_a, c_s  */
 159 
 160   /* The location of the center of the voxel at CRS = (0,0,0)*/
 161   *MATRIX_RELT(m, 1, 4) = mri->c_r - PxyzOffset->rptr[1][1];
 162   *MATRIX_RELT(m, 2, 4) = mri->c_a - PxyzOffset->rptr[2][1];
 163   *MATRIX_RELT(m, 3, 4) = mri->c_s - PxyzOffset->rptr[3][1];
 164 
 165   MatrixFree(&Pcrs);
 166   MatrixFree(&PxyzOffset);
 167 
 168   return(m);
 169 }
 170 /*-------------------------------------------------------------
 171   MRIxfmCRS2XYZtkreg() - computes the linear transform between the
 172   column, row, and slice of a voxel and the x, y, z of that voxel as
 173   expected by tkregister (or for when using a tkregister compatible
 174   matrix). For tkregister, the column DC points in the "x" direction,
 175   the row DC points in the "z" direction, and the slice DC points in
 176   the "y" direction. The center of the coordinates is set to the
 177   center of the FOV. These definitions are arbitrary (and more than a
 178   little confusing). Since they are arbitrary, they must be applied
 179   consistently.
 180   -------------------------------------------------------------*/
 181 MATRIX *MRIxfmCRS2XYZtkreg(MRI *mri)
 182 {
 183   MRI *tmp;
 184   MATRIX *K;
 185 
 186   tmp = MRIallocHeader(mri->width, mri->height, mri->depth, mri->type);
 187 
 188   /* Set tkregister defaults */
 189   /* column         row           slice          center      */
 190   tmp->x_r = -1; tmp->y_r =  0; tmp->z_r =  0; tmp->c_r = 0.0;
 191   tmp->x_a =  0; tmp->y_a =  0; tmp->z_a =  1; tmp->c_a = 0.0;
 192   tmp->x_s =  0; tmp->y_s = -1; tmp->z_s =  0; tmp->c_s = 0.0;
 193 
 194   /* Copy the voxel resolutions */
 195   tmp->xsize = mri->xsize;
 196   tmp->ysize = mri->ysize;
 197   tmp->zsize = mri->zsize;
 198 
 199   K = MRIxfmCRS2XYZ(tmp,0);
 200 
 201   MRIfree(&tmp);
 202 
 203   return(K);
 204 }
 205 /*-------------------------------------------------------------------
 206   MRItkReg2Native() - converts a tkregister-compatible registration matrix
 207   R to one that works with the geometry native to the two volumes. The
 208   matrix R maps tkXYZ of the ref volume to tkXYZ of the mov volume. In
 209   a typical application, ref is the anatomical volume and mov is the
 210   functional volume. The purpose of this function is to be able to use
 211   registration matrices computed by (or compatible with) tkregister
 212   without losing the geometries native to the volumes. If R is null,
 213   it is assumed to be the identity. R: MovXYZ = R*RefXYZ. Typically,
 214   Ref is the Anatomical Reference, and Mov is the functional.
 215 
 216   See also: MRItkRegMtx, MRIxfmCRS2XYZtkreg, MRIxfmCRS2XYZ
 217   -------------------------------------------------------------------*/
 218 MATRIX *MRItkReg2Native(MRI *ref, MRI *mov, MATRIX *R)
 219 {
 220   MATRIX *Kref, *Kmov;
 221   MATRIX *Tref, *Tmov, *D;
 222   MATRIX *invKmov, *invTref;
 223 
 224   Tref = MRIxfmCRS2XYZ(ref,0);
 225   Tmov = MRIxfmCRS2XYZ(mov,0);
 226 
 227   Kref = MRIxfmCRS2XYZtkreg(ref);
 228   Kmov = MRIxfmCRS2XYZtkreg(mov);
 229 
 230   /* D = Tmov * inv(Kmov) * R * Kref *inv(Tref) */
 231   invKmov = MatrixInverse(Kmov,NULL);
 232   invTref = MatrixInverse(Tref,NULL);
 233 
 234   D = MatrixMultiply(Tmov,invKmov,NULL);
 235   if(R!=NULL) MatrixMultiply(D,R,D);
 236   MatrixMultiply(D,Kref,D);
 237   MatrixMultiply(D,invTref,D);
 238 
 239   if(0) {
 240     printf("MRITkReg2Native -----------------------------\n");
 241     printf("Tref ----------------\n");
 242     MatrixPrint(stdout,Tref);
 243     printf("Tmov ----------------\n");
 244     MatrixPrint(stdout,Tmov);
 245     printf("Kref ----------------\n");
 246     MatrixPrint(stdout,Kref);
 247     printf("Kmov ----------------\n");
 248     MatrixPrint(stdout,Kmov);
 249     printf("------------------------------------------\n");
 250   }
 251 
 252   MatrixFree(&Kref);
 253   MatrixFree(&Tref);
 254   MatrixFree(&Kmov);
 255   MatrixFree(&Tmov);
 256   MatrixFree(&invKmov);
 257   MatrixFree(&invTref);
 258 
 259   return(D);
 260 }
 261 /*----------------------------------------------------------------
 262   MRItkRegMtx() - creates a tkregsiter-compatible matrix from the
 263   matrix D that aligns the two volumes assuming the native geometry.
 264   This is the counterpart to MRITkReg2Native(). If D is null, it is
 265   assumed to be the identity. R: MovXYZ = R*RefXYZ. Typically,
 266   Ref is the Anatomical Reference, and Mov is the functional.
 267   Use this function with D=NULL when the two volumes have been
 268   aligned with SPM.
 269   ---------------------------------------------------------------*/
 270 MATRIX *MRItkRegMtx(MRI *ref, MRI *mov, MATRIX *D)
 271 {
 272   MATRIX *Kref, *Kmov;
 273   MATRIX *Tref, *Tmov, *R;
 274   MATRIX *invTmov, *invKref;
 275 
 276   /* Native Goemetry */
 277   Tref = MRIxfmCRS2XYZ(ref,0);
 278   Tmov = MRIxfmCRS2XYZ(mov,0);
 279 
 280   /* TkReg Goemetry */
 281   Kref = MRIxfmCRS2XYZtkreg(ref);
 282   Kmov = MRIxfmCRS2XYZtkreg(mov);
 283 
 284   invTmov = MatrixInverse(Tmov,NULL);
 285   invKref = MatrixInverse(Kref,NULL);
 286 
 287   /* R = Kmov * inv(Tmov) * D * Tref *inv(Kref) */
 288   R = MatrixMultiply(Kmov,invTmov,NULL);
 289   if(D != NULL) MatrixMultiply(R,D,R);
 290   MatrixMultiply(R,Tref,R);
 291   MatrixMultiply(R,invKref,R);
 292 
 293   MatrixFree(&Kref);
 294   MatrixFree(&Tref);
 295   MatrixFree(&Kmov);
 296   MatrixFree(&Tmov);
 297   MatrixFree(&invTmov);
 298   MatrixFree(&invKref);
 299 
 300   return(R);
 301 }
 302 /*-------------------------------------------------------------
 303   MRIfixTkReg() - this routine will adjust a matrix created by the
 304   "old" tkregister program. The old program had a problem in the way
 305   it chose the CRS of a voxel in the functional volume based on a
 306   point in the anatomical volume. The functional CRS of a point in
 307   anatomical space rarely (if ever) falls directly on a functional
 308   voxel, so it's necessary to choose a functional voxel given that the
 309   point falls between functional voxels (or it can be interpolated).
 310   The old tkregister program did not interpolate, rather it would
 311   choose the CRS in the following way: iC = floor(fC), iR = ceil(fR),
 312   and iS = floor(fS), where iC is the integer column number and fC is
 313   the floating point column, etc. Unfortunately, this is not nearest
 314   neighbor and it's not invertible. The right way to do it is to do
 315   nearest neighbor (ie, round to the closest integer). Unfortunately,
 316   there are a lot of data sets out there that have been regsitered
 317   with the old program, and we don't want to force poeple to
 318   reregister with the "new" program. This routine attempts to adjust
 319   the matrix created with the old program so that it will work with
 320   code that assumes that pure nearest neighbor was used.
 321 
 322   It does this by randomly sampling the anatomical volume in xyz
 323   and computing the tkreg'ed CRS for each point.
 324 
 325   Pcrs = inv(Tmov)*R*Pxyz
 326   PcrsTkReg = fcf(Pcrs) -- fcf is floor ceiling floor
 327 
 328   We seek a new R (Rfix) define with
 329 
 330   PcrsFix = inv(Tmov)*Rfix*Pxyz
 331 
 332   such that that the difference between PcrsFix and PcrsTkReg are
 333   minimized. To do this, we set
 334 
 335   PcrsFix = PcrsTkReg = inv(Tmov)*Rfix*Pxyz
 336 
 337   and solve for Rfix (this is an LMS solution):
 338 
 339   Rfix = Tmov*(PcrsTkReg*Pxyz')*inv(Pxyz*Pxyz');
 340 
 341   Applications that read in the registration matrix should detect the
 342   truncation method used (see below), fix the matrix if necessary, and
 343   proceed as if nearest neighbor/rounding was used.  The type of
 344   truncation can be determined from the last line of the registration
 345   file (after the matrix itself). If there is nothing there or the
 346   string "tkregister" is there, then the matrix should be
 347   converted. Otherwise, the string "round" should be there. The
 348   function regio_read_register (from registerio.c) will return the
 349   type of matrix in the float2int variable. It will be either
 350   FLT2INT_TKREG or FLT2INT_ROUND (constants defined in resample.h).
 351   ---------------------------------------------------------------*/
 352 MATRIX *MRIfixTkReg(MRI *mov, MATRIX *R)
 353 {
 354   int n, ntest = 1000;
 355   MATRIX *Pxyz, *Pcrs, *PcrsTkReg;
 356   MATRIX *PxyzT, *PxyzPxyzT, *invPxyzPxyzT;
 357   MATRIX *Tmov,*invTmov,*Rfix;
 358   MATRIX *tmp;
 359   float xrange, yrange, zrange;
 360 
 361   /* Assume a COR reference image */
 362   xrange = 256.0;
 363   yrange = 256.0;
 364   zrange = 256.0;
 365 
 366   Tmov = MRIxfmCRS2XYZtkreg(mov);
 367   invTmov = MatrixInverse(Tmov,NULL);
 368 
 369   Pxyz      = MatrixAlloc(4,ntest,MATRIX_REAL);
 370   PcrsTkReg = MatrixAlloc(4,ntest,MATRIX_REAL);
 371 
 372   /* Fill xyz with rand within the reference volume range */
 373   for(n=0;n<ntest;n++) {
 374     Pxyz->rptr[1][n+1] = xrange * (drand48()-0.5);
 375     Pxyz->rptr[2][n+1] = yrange * (drand48()-0.5);
 376     Pxyz->rptr[3][n+1] = zrange * (drand48()-0.5);
 377     Pxyz->rptr[4][n+1] = 1;
 378   }
 379 
 380   /* Compute floating mov CRS from targ XYZ */
 381   /* Pcrs = inv(Tmov)*R*Pxyz */
 382   tmp = MatrixMultiply(R,Pxyz,NULL);
 383   Pcrs = MatrixMultiply(invTmov,tmp,NULL);
 384   MatrixFree(&tmp);
 385 
 386   /* Truncate floating mov CRS using tkregister method*/
 387   for(n=0;n<ntest;n++) {
 388     PcrsTkReg->rptr[1][n+1] = floor(Pcrs->rptr[1][n+1]);
 389     PcrsTkReg->rptr[2][n+1] =  ceil(Pcrs->rptr[2][n+1]);
 390     PcrsTkReg->rptr[3][n+1] = floor(Pcrs->rptr[3][n+1]);
 391     PcrsTkReg->rptr[4][n+1] = 1;
 392   }
 393   MatrixFree(&Pcrs);
 394 
 395   //Rfix = Tmov*(PcrsTkreg*Pxyz')*inv(Pxyz*Pxyz');
 396   PxyzT = MatrixTranspose(Pxyz,NULL);
 397   PxyzPxyzT = MatrixMultiply(Pxyz,PxyzT,NULL);
 398   invPxyzPxyzT = MatrixInverse(PxyzPxyzT,NULL);
 399   tmp = MatrixMultiply(PcrsTkReg,PxyzT,NULL);
 400   MatrixMultiply(Tmov,tmp,tmp);
 401   Rfix = MatrixMultiply(tmp,invPxyzPxyzT,NULL);
 402 
 403 
 404   MatrixFree(&Pxyz);
 405   MatrixFree(&PcrsTkReg);
 406   MatrixFree(&PxyzT);
 407   MatrixFree(&PxyzPxyzT);
 408   MatrixFree(&invPxyzPxyzT);
 409   MatrixFree(&Tmov);
 410   MatrixFree(&invTmov);
 411   MatrixFree(&tmp);
 412 
 413   return(Rfix);
 414 }
 415 
 416 /*-------------------------------------------------------------------
 417   MRIfsl2TkReg() - converts an FSL registration matrix to one
 418   compatible with tkregister.  Note: the FSL matrix is assumed to map
 419   from the mov to the ref whereas the tkreg matrix maps from the ref
 420   to the mov.
 421 
 422   mov voxel --(Tmov)--> tkRegXYZ(mov)
 423   ^                          ^
 424   | inv(Dmov)                |
 425   |                          |
 426   mov' physvox                |
 427   ^                          |
 428   | inv(Mfsl)                | R
 429   |                          |
 430   ref' physvox                |
 431   ^                          |
 432   | Dref                     |
 433   |                          |
 434   ref voxel <--inv(Tref)--tkRegXYZ(ref)
 435   -------------------------------------------------------------------*/
 436 MATRIX *MRIfsl2TkReg(MRI *ref, MRI *mov, MATRIX *FSLRegMat)
 437 {
 438   MATRIX *RegMat=NULL, *invDmov, *Tmov, *Dref;
 439   MATRIX *invFSLRegMat, *invTref, *Tref;
 440 
 441   /* R = Tmov * inv(Dmov) * inv(Mfsl) * Dref * inv(Tref) */
 442   invDmov = MatrixAlloc(4,4,MATRIX_REAL);
 443   invDmov->rptr[1][1] = 1.0/mov->xsize;
 444   invDmov->rptr[2][2] = 1.0/mov->ysize;
 445   invDmov->rptr[3][3] = 1.0/mov->zsize;
 446   invDmov->rptr[4][4] = 1.0;
 447 
 448   Dref = MatrixAlloc(4,4,MATRIX_REAL);
 449   Dref->rptr[1][1] = ref->xsize;
 450   Dref->rptr[2][2] = ref->ysize;
 451   Dref->rptr[3][3] = ref->zsize;
 452   Dref->rptr[4][4] = 1.0;
 453 
 454   Tmov = MRIxfmCRS2XYZtkreg(mov);
 455   Tref = MRIxfmCRS2XYZtkreg(ref);
 456   invTref = MatrixInverse(Tref,NULL);
 457 
 458   invFSLRegMat = MatrixInverse(FSLRegMat,NULL);
 459 
 460   RegMat = MatrixMultiply(Tmov,invDmov,RegMat);
 461   RegMat = MatrixMultiply(RegMat,invFSLRegMat,RegMat);
 462   RegMat = MatrixMultiply(RegMat,Dref,RegMat);
 463   RegMat = MatrixMultiply(RegMat,invTref,RegMat);
 464 
 465   MatrixFree(&invDmov);
 466   MatrixFree(&FSLRegMat);
 467   MatrixFree(&invFSLRegMat);
 468   MatrixFree(&Tmov);
 469   MatrixFree(&Tref);
 470   MatrixFree(&invTref);
 471   MatrixFree(&Dref);
 472 
 473   return(RegMat);
 474 }
 475 /*-------------------------------------------------------------------
 476   MRItkreg2FSL() - converts tkregister registration matrix to one
 477   compatible with FSL. Note: the FSL matrix is assumed to map from the
 478   mov to the ref whereas the tkreg matrix maps from the ref to the
 479   mov.
 480 
 481   mov voxel<--inv(Tmov)-- tkRegXYZ(mov)
 482   |                           ^
 483   |  Dmov                     |
 484   V                           |
 485   mov' physvox                 |
 486   |                           |
 487   |  Mfsl                     | R
 488   V                           |
 489   ref' physvox                 |
 490   |                           |
 491   |  inv(Dref)                |
 492   V                           |
 493   ref voxel -- Tref  -->  tkRegXYZ(ref)
 494 
 495   -------------------------------------------------------------------*/
 496 MATRIX *MRItkreg2FSL(MRI *ref, MRI *mov, MATRIX *tkRegMat)
 497 {
 498   MATRIX *FSLRegMat=NULL, *Dmov, *Tmov, *invTmov, *Tref, *Dref, *invDref;
 499 
 500   /* R = Tmov * inv(Dmov) * inv(Mfsl) * Dref * inv(Tref) */
 501   /* Mfsl =  inv( Dmov * inv(Tmov) * R * Tref * inv(Dref)) */
 502   Dmov = MatrixAlloc(4,4,MATRIX_REAL);
 503   Dmov->rptr[1][1] = mov->xsize;
 504   Dmov->rptr[2][2] = mov->ysize;
 505   Dmov->rptr[3][3] = mov->zsize;
 506   Dmov->rptr[4][4] = 1.0;
 507 
 508   Dref = MatrixAlloc(4,4,MATRIX_REAL);
 509   Dref->rptr[1][1] = ref->xsize;
 510   Dref->rptr[2][2] = ref->ysize;
 511   Dref->rptr[3][3] = ref->zsize;
 512   Dref->rptr[4][4] = 1.0;
 513   invDref = MatrixInverse(Dref,NULL);
 514 
 515   Tmov = MRIxfmCRS2XYZtkreg(mov);
 516   invTmov = MatrixInverse(Tmov,NULL);
 517   Tref = MRIxfmCRS2XYZtkreg(ref);
 518 
 519   FSLRegMat = MatrixMultiply(Dmov,invTmov,FSLRegMat);
 520   FSLRegMat = MatrixMultiply(FSLRegMat,tkRegMat,FSLRegMat);
 521   FSLRegMat = MatrixMultiply(FSLRegMat,Tref,FSLRegMat);
 522   FSLRegMat = MatrixMultiply(FSLRegMat,invDref,FSLRegMat);
 523   FSLRegMat = MatrixInverse(FSLRegMat,FSLRegMat);
 524 
 525   if(0){
 526     printf("--- Dmov ---------------------\n");
 527     MatrixPrint(stdout,Dmov);
 528     printf("--- Tmov ---------------------\n");
 529     MatrixPrint(stdout,Tmov);
 530     printf("--- R ---------------------\n");
 531     MatrixPrint(stdout,tkRegMat);
 532     printf("--- Tref ---------------------\n");
 533     MatrixPrint(stdout,Tref);
 534     printf("--- Dref ---------------------\n");
 535     MatrixPrint(stdout,Dref);
 536     printf("--- Rfsl ---------------------\n");
 537     MatrixPrint(stdout,FSLRegMat);
 538     printf("--- R (from Rfsl) ------------\n");
 539     tkRegMat = MRIfsl2TkReg(ref,mov,FSLRegMat);
 540     MatrixPrint(stdout,tkRegMat);
 541   }
 542 
 543   MatrixFree(&Dmov);
 544   MatrixFree(&Tmov);
 545   MatrixFree(&invTmov);
 546   MatrixFree(&Tref);
 547   MatrixFree(&Dref);
 548   MatrixFree(&invDref);
 549 
 550   return(FSLRegMat);
 551 }
 552 
 553 /*--------------------------------------------------------------------------
 554   MtxCRS1toCRS0() - generates a matrix that will convert 1-based CRS (as
 555   found in SPM matrices) to 0-based CRS, ie, CRS0 = Q*CRS1 (assuming that
 556   CRS1 has been packed with a 1 in the 4th component.
 557   --------------------------------------------------------------------------*/
 558 MATRIX *MtxCRS1toCRS0(MATRIX *Q)
 559 {
 560   int r,c;
 561 
 562   if(Q == NULL) Q = MatrixAlloc(4,4,MATRIX_REAL);
 563   else{
 564     if(Q->rows != 4 || Q->cols != 4){
 565       printf("ERROR: MtxCRS1toCRS0(): input matrix is not 4x4\n");
 566       return(NULL);
 567     }
 568   }
 569 
 570   for(r=1;r<=4;r++){
 571     for(c=1;c<=4;c++){
 572       if(r==c || c==4) Q->rptr[r][c] = 1.0;
 573       else             Q->rptr[r][c] = 0.0;
 574     }
 575   }
 576 
 577   return(Q);
 578 }
 579 
 580 
 581 /*-------------------------------------------------------------------
 582   MRIgetVoxVal() - returns voxel value as a float regardless of
 583   the underlying data type.
 584   -------------------------------------------------------------------*/
 585 float MRIgetVoxVal(MRI *mri, int c, int r, int s, int f)
 586 {
 587   switch(mri->type){
 588   case MRI_UCHAR: return( (float) MRIseq_vox(mri,c,r,s,f)); break;
 589   case MRI_SHORT: return( (float) MRISseq_vox(mri,c,r,s,f)); break;
 590   case MRI_INT:   return( (float) MRIIseq_vox(mri,c,r,s,f)); break;
 591   case MRI_LONG:  return( (float) MRILseq_vox(mri,c,r,s,f)); break;
 592   case MRI_FLOAT: return( (float) MRIFseq_vox(mri,c,r,s,f)); break;
 593   }
 594   return(-10000000000.9);
 595 }
 596 /*-------------------------------------------------------------------
 597   MRIsetVoxVal() - sets voxel value to that passed as the float
 598   voxval, regardless of the underlying data type. If the underlying
 599   type is integer-based, then it is rounded to the nearest integer. No
 600   attempt is made to prevent overflows.
 601   -------------------------------------------------------------------*/
 602 int MRIsetVoxVal(MRI *mri, int c, int r, int s, int f, float voxval)
 603 {
 604   switch(mri->type){
 605   case MRI_UCHAR: MRIseq_vox(mri,c,r,s,f)  = nint(voxval); break;
 606   case MRI_SHORT: MRISseq_vox(mri,c,r,s,f) = nint(voxval); break;
 607   case MRI_INT:   MRIIseq_vox(mri,c,r,s,f) = nint(voxval); break;
 608   case MRI_LONG:  MRILseq_vox(mri,c,r,s,f) = nint(voxval); break;
 609   case MRI_FLOAT: MRIFseq_vox(mri,c,r,s,f) = voxval;       break;
 610   default: return(1); break;
 611   }
 612   return(0);
 613 }
 614 
 615 /*------------------------------------------------------------------
 616   MRIinterpCode() - returns the numeric interpolation code given the
 617   name of the interpolation method.
 618   -----------------------------------------------------------------*/
 619 int MRIinterpCode(char *InterpString)
 620 {
 621   if(!strncasecmp(InterpString,"nearest",3))
 622     return(SAMPLE_NEAREST);
 623   if(!strncasecmp(InterpString,"trilinear",3))
 624     return(SAMPLE_TRILINEAR);
 625   if(!strncasecmp(InterpString,"sinc",3))
 626     return(SAMPLE_SINC);
 627   if(!strncasecmp(InterpString,"cubic",3))
 628     return(SAMPLE_CUBIC);
 629 
 630   return(-1);
 631 }
 632 
 633 /*------------------------------------------------------------------
 634   MRIinterpString() - returns the the name of the interpolation method
 635   given numeric interpolation code
 636   -----------------------------------------------------------------*/
 637 char * MRIinterpString(int InterpCode)
 638 {
 639   switch (InterpCode)
 640     {
 641     case SAMPLE_NEAREST:   return("nearest"); break ;
 642     case SAMPLE_TRILINEAR: return("trilinear"); break ;
 643     case SAMPLE_SINC:      return("sinc"); break ;
 644     case SAMPLE_CUBIC:     return("cubic"); break ;
 645     }
 646   return(NULL);
 647 }
 648 /*------------------------------------------------------------------
 649   MRIprecisionCode() - returns the numeric code given the
 650   name of the precision. This corresponds to the value of the type
 651   field in the MRI structure.
 652   -----------------------------------------------------------------*/
 653 int MRIprecisionCode(char *PrecisionString)
 654 {
 655   if(!strcasecmp(PrecisionString,"uchar"))
 656     return(MRI_UCHAR);
 657   if(!strcasecmp(PrecisionString,"short"))
 658     return(MRI_SHORT);
 659   if(!strcasecmp(PrecisionString,"int"))
 660     return(MRI_INT);
 661   if(!strcasecmp(PrecisionString,"long"))
 662     return(MRI_LONG);
 663   if(!strcasecmp(PrecisionString,"float"))
 664     return(MRI_FLOAT);
 665 
 666   return(-1);
 667 }
 668 
 669 /*------------------------------------------------------------------
 670   MRIprecisionString() - returns the the name of the precision given
 671   numeric precision code. The code corresponds to the value of the
 672   type field in the MRI structure.
 673   -----------------------------------------------------------------*/
 674 char * MRIprecisionString(int PrecisionCode)
 675 {
 676   switch (PrecisionCode)
 677     {
 678     case MRI_UCHAR: return("uchar"); break ;
 679     case MRI_SHORT: return("short"); break ;
 680     case MRI_INT:   return("int"); break ;
 681     case MRI_LONG:  return("long"); break ;
 682     case MRI_FLOAT: return("float"); break ;
 683     }
 684   return(NULL);
 685 }
 686 
 687 /*-----------------------------------------------------
 688   ------------------------------------------------------*/
 689 int
 690 MRImatch(MRI *mri1, MRI *mri2)
 691 {
 692   return(
 693          (mri1->width == mri2->width) &&
 694          (mri1->height == mri2->height) &&
 695          (mri1->depth == mri2->depth) &&
 696          (mri1->type == mri2->type)
 697          ) ;
 698 }
 699 /*-----------------------------------------------------
 700   ------------------------------------------------------*/
 701 MRI *
 702 MRIscalarMul(MRI *mri_src, MRI *mri_dst, float scalar)
 703 {
 704   int     width, height, depth, x, y, z, frame ;
 705   BUFTYPE *psrc, *pdst ;
 706   float   *pfsrc, *pfdst, dval ;
 707   short   *pssrc, *psdst ;
 708 
 709   width = mri_src->width ;
 710   height = mri_src->height ;
 711   depth = mri_src->depth ;
 712   if (!mri_dst)
 713     mri_dst = MRIclone(mri_src, NULL) ;
 714 
 715   for (frame = 0 ; frame < mri_src->nframes ; frame++)
 716     {
 717       for (z = 0 ; z < depth ; z++)
 718         {
 719           for (y = 0 ; y < height ; y++)
 720             {
 721               switch (mri_src->type)
 722                 {
 723                 case MRI_UCHAR:
 724                   psrc = &MRIseq_vox(mri_src, 0, y, z, frame) ;
 725                   pdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
 726                   for (x = 0 ; x < width ; x++)
 727                     {
 728                       dval = *psrc++ * scalar ;
 729                       if (dval < 0)
 730                         dval = 0 ;
 731                       if (dval > 255)
 732                         dval = 255 ;
 733                       *pdst++ = dval ;
 734                     }
 735                   break ;
 736                 case MRI_FLOAT:
 737                   pfsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
 738                   pfdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
 739                   for (x = 0 ; x < width ; x++)
 740                     *pfdst++ = *pfsrc++ * scalar ;
 741                   break ;
 742                 case MRI_SHORT:
 743                   pssrc = &MRISseq_vox(mri_src, 0, y, z, frame) ;
 744                   psdst = &MRISseq_vox(mri_dst, 0, y, z, frame) ;
 745                   for (x = 0 ; x < width ; x++)
 746                     *psdst++ = (short)nint((float)*pssrc++ * scalar) ;
 747                   break ;
 748                 default:
 749                   ErrorReturn
 750                     (NULL,
 751                      (ERROR_UNSUPPORTED,
 752                       "MRIscalarMul: unsupported type %d", mri_src->type)) ;
 753                 }
 754             }
 755         }
 756     }
 757   return(mri_dst) ;
 758 }
 759 /*-----------------------------------------------------
 760   ------------------------------------------------------*/
 761 MRI *
 762 MRIscalarMulFrame(MRI *mri_src, MRI *mri_dst, float scalar, int frame)
 763 {
 764   int     width, height, depth, x, y, z ;
 765   BUFTYPE *psrc, *pdst ;
 766   float   *pfsrc, *pfdst, dval ;
 767   short   *pssrc, *psdst ;
 768 
 769   width = mri_src->width ;
 770   height = mri_src->height ;
 771   depth = mri_src->depth ;
 772   if (!mri_dst)
 773     mri_dst = MRIclone(mri_src, NULL) ;
 774 
 775   for (z = 0 ; z < depth ; z++)
 776     {
 777       for (y = 0 ; y < height ; y++)
 778         {
 779           switch (mri_src->type)
 780             {
 781             case MRI_UCHAR:
 782               psrc = &MRIseq_vox(mri_src, 0, y, z, frame) ;
 783               pdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
 784               for (x = 0 ; x < width ; x++)
 785                 {
 786                   dval = *psrc++ * scalar ;
 787                   if (dval < 0)
 788                     dval = 0 ;
 789                   if (dval > 255)
 790                     dval = 255 ;
 791                   *pdst++ = dval ;
 792                 }
 793               break ;
 794             case MRI_FLOAT:
 795               pfsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
 796               pfdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
 797               for (x = 0 ; x < width ; x++)
 798                 *pfdst++ = *pfsrc++ * scalar ;
 799               break ;
 800             case MRI_SHORT:
 801               pssrc = &MRISseq_vox(mri_src, 0, y, z, frame) ;
 802               psdst = &MRISseq_vox(mri_dst, 0, y, z, frame) ;
 803               for (x = 0 ; x < width ; x++)
 804                 *psdst++ = (short)nint((float)*pssrc++ * scalar) ;
 805               break ;
 806             default:
 807               ErrorReturn
 808                 (NULL,
 809                  (ERROR_UNSUPPORTED,
 810                   "MRIscalarMulFrame: unsupported type %d", mri_src->type)) ;
 811             }
 812         }
 813     }
 814   return(mri_dst) ;
 815 }
 816 /*-----------------------------------------------------
 817   ------------------------------------------------------*/
 818 int
 819 MRIvalRange(MRI *mri, float *pmin, float *pmax)
 820 {
 821   int      width, height, depth, x, y, z, frame ;
 822   float    fmin, fmax, *pf, val ;
 823   BUFTYPE  *pb ;
 824 
 825   width = mri->width ;
 826   height = mri->height ;
 827   depth = mri->depth ;
 828 
 829   fmin = 10000.0f ;
 830   fmax = -10000.0f ;
 831   switch (mri->type)
 832     {
 833     case MRI_FLOAT:
 834       for (frame = 0 ; frame < mri->nframes ; frame++)
 835         {
 836           for (z = 0 ; z < depth ; z++)
 837             {
 838               for (y = 0 ; y < height ; y++)
 839                 {
 840                   pf = &MRIFseq_vox(mri, 0, y, z, frame) ;
 841                   for (x = 0 ; x < width ; x++)
 842                     {
 843                       val = *pf++ ;
 844                       if (val < fmin)
 845                         fmin = val ;
 846                       if (val > fmax)
 847                         fmax = val ;
 848                     }
 849                 }
 850             }
 851         }
 852       break ;
 853     case MRI_INT:
 854       for (frame = 0 ; frame < mri->nframes ; frame++)
 855         {
 856           for (z = 0 ; z < depth ; z++)
 857             {
 858               for (y = 0 ; y < height ; y++)
 859                 {
 860                   for (x = 0 ; x < width ; x++)
 861                     {
 862                       val = (float)MRIIseq_vox(mri, x, y, z, frame) ;
 863                       if (val < fmin)
 864                         fmin = val ;
 865                       if (val > fmax)
 866                         fmax = val ;
 867                     }
 868                 }
 869             }
 870         }
 871       break ;
 872     case MRI_SHORT:
 873       for (frame = 0 ; frame < mri->nframes ; frame++)
 874         {
 875           for (z = 0 ; z < depth ; z++)
 876             {
 877               for (y = 0 ; y < height ; y++)
 878                 {
 879                   for (x = 0 ; x < width ; x++)
 880                     {
 881                       val = (float)MRISseq_vox(mri, x, y, z, frame) ;
 882                       if (val < fmin)
 883                         fmin = val ;
 884                       if (val > fmax)
 885                         fmax = val ;
 886                     }
 887                 }
 888             }
 889         }
 890       break ;
 891     case MRI_UCHAR:
 892       for (frame = 0 ; frame < mri->nframes ; frame++)
 893         {
 894           for (z = 0 ; z < depth ; z++)
 895             {
 896               for (y = 0 ; y < height ; y++)
 897                 {
 898                   pb = &MRIseq_vox(mri, 0, y, z, frame) ;
 899                   for (x = 0 ; x < width ; x++)
 900                     {
 901                       val = (float)*pb++ ;
 902                       if (val < fmin)
 903                         fmin = val ;
 904                       if (val > fmax)
 905                         fmax = val ;
 906                     }
 907                 }
 908             }
 909         }
 910       break ;
 911     default:
 912       for (frame = 0 ; frame < mri->nframes ; frame++)
 913         {
 914           for (z = 0 ; z < depth ; z++)
 915             {
 916               for (y = 0 ; y < height ; y++)
 917                 {
 918                   for (x = 0 ; x < width ; x++)
 919                     {
 920                       val = (float)MRIgetVoxVal(mri, x, y, z, frame) ;
 921                       if (val < fmin)
 922                         fmin = val ;
 923                       if (val > fmax)
 924                         fmax = val ;
 925                     }
 926                 }
 927             }
 928         }
 929       break ;
 930     }
 931 
 932   *pmin = fmin ;
 933   *pmax = fmax ;
 934   return(NO_ERROR) ;
 935 }
 936 int
 937 MRInonzeroValRange(MRI *mri, float *pmin, float *pmax)
 938 {
 939   int      width, height, depth, x, y, z, frame ;
 940   float    fmin, fmax, val ;
 941 
 942   width = mri->width ;
 943   height = mri->height ;
 944   depth = mri->depth ;
 945 
 946   fmin = 10000.0f ;
 947   fmax = -10000.0f ;
 948   for (frame = 0 ; frame < mri->nframes ; frame++)
 949     {
 950       for (z = 0 ; z < depth ; z++)
 951         {
 952           for (y = 0 ; y < height ; y++)
 953             {
 954               for (x = 0 ; x < width ; x++)
 955                 {
 956                   val = MRIgetVoxVal(mri, x, y, z, 0) ;
 957                   if (FZERO(val))
 958                     continue ;
 959                   if (val < fmin)
 960                     fmin = val ;
 961                   if (val > fmax)
 962                     fmax = val ;
 963                 }
 964             }
 965         }
 966     }
 967 
 968   *pmin = fmin ;
 969   *pmax = fmax ;
 970   return(NO_ERROR) ;
 971 }
 972 /*-----------------------------------------------------
 973   ------------------------------------------------------*/
 974 int
 975 MRIvalRangeFrame(MRI *mri, float *pmin, float *pmax, int frame)
 976 {
 977   int      width, height, depth, x, y, z ;
 978   float    fmin, fmax, *pf, val ;
 979   BUFTYPE  *pb ;
 980 
 981   width = mri->width ;
 982   height = mri->height ;
 983   depth = mri->depth ;
 984 
 985   fmin = 10000.0f ;
 986   fmax = -10000.0f ;
 987   switch (mri->type)
 988     {
 989     case MRI_FLOAT:
 990       for (z = 0 ; z < depth ; z++)
 991         {
 992           for (y = 0 ; y < height ; y++)
 993             {
 994               pf = &MRIFseq_vox(mri, 0, y, z, frame) ;
 995               for (x = 0 ; x < width ; x++)
 996                 {
 997                   val = *pf++ ;
 998                   if (val < fmin)
 999                     fmin = val ;
1000                   if (val > fmax)
1001                     fmax = val ;
1002                 }
1003             }
1004         }
1005       break ;
1006     case MRI_INT:
1007       for (z = 0 ; z < depth ; z++)
1008         {
1009           for (y = 0 ; y < height ; y++)
1010             {
1011               for (x = 0 ; x < width ; x++)
1012                 {
1013                   val = (float)MRIIseq_vox(mri, x, y, z, frame) ;
1014                   if (val < fmin)
1015                     fmin = val ;
1016                   if (val > fmax)
1017                     fmax = val ;
1018                 }
1019             }
1020         }
1021       break ;
1022     case MRI_SHORT:
1023       for (z = 0 ; z < depth ; z++)
1024         {
1025           for (y = 0 ; y < height ; y++)
1026             {
1027               for (x = 0 ; x < width ; x++)
1028                 {
1029                   val = (float)MRISseq_vox(mri, x, y, z, frame) ;
1030                   if (val < fmin)
1031                     fmin = val ;
1032                   if (val > fmax)
1033                     fmax = val ;
1034                 }
1035             }
1036         }
1037       break ;
1038     case MRI_UCHAR:
1039       for (z = 0 ; z < depth ; z++)
1040         {
1041           for (y = 0 ; y < height ; y++)
1042             {
1043               pb = &MRIseq_vox(mri, 0, y, z, frame) ;
1044               for (x = 0 ; x < width ; x++)
1045                 {
1046                   val = (float)*pb++ ;
1047                   if (val < fmin)
1048                     fmin = val ;
1049                   if (val > fmax)
1050                     fmax = val ;
1051                 }
1052             }
1053         }
1054       break ;
1055     default:
1056       ErrorReturn(ERROR_UNSUPPORTED,
1057                   (ERROR_UNSUPPORTED, "MRIvalRange: unsupported type %d",
1058                    mri->type)) ;
1059     }
1060 
1061   *pmin = fmin ;
1062   *pmax = fmax ;
1063   return(NO_ERROR) ;
1064 }
1065 /*-----------------------------------------------------
1066   ------------------------------------------------------*/
1067 int
1068 MRIvalRangeRegion(MRI *mri, float *pmin, float *pmax, MRI_REGION *region)
1069 {
1070   int      width, height, depth, x, y, z, x0, y0, z0 ;
1071   float    fmin, fmax, *pf, val ;
1072   BUFTYPE  *pb ;
1073 
1074   width = region->x + region->dx ;
1075   if (width > mri->width)
1076     width = mri->width ;
1077   height = region->y + region->dy ;
1078   if (height > mri->height)
1079     height = mri->height ;
1080   depth = region->z + region->dz ;
1081   if (depth > mri->depth)
1082     depth = mri->depth ;
1083   x0 = region->x ;
1084   if (x0 < 0)
1085     x0 = 0 ;
1086   y0 = region->y ;
1087   if (y0 < 0)
1088     y0 = 0 ;
1089   z0 = region->z ;
1090   if (z0 < 0)
1091     z0 = 0 ;
1092 
1093   fmin = 10000.0f ;
1094   fmax = -10000.0f ;
1095   switch (mri->type)
1096     {
1097     default:
1098       for (z = z0 ; z < depth ; z++)
1099         {
1100           for (y = y0 ; y < height ; y++)
1101             {
1102               pf = &MRIFvox(mri, x0, y, z) ;
1103               for (x = x0 ; x < width ; x++)
1104                 {
1105                   val = MRIgetVoxVal(mri, x, y, z, 0) ;
1106                   if (val < fmin)
1107                     fmin = val ;
1108                   if (val > fmax)
1109                     fmax = val ;
1110                 }
1111             }
1112         }
1113       break ;
1114 
1115     case MRI_FLOAT:
1116       for (z = z0 ; z < depth ; z++)
1117         {
1118           for (y = y0 ; y < height ; y++)
1119             {
1120               pf = &MRIFvox(mri, x0, y, z) ;
1121               for (x = x0 ; x < width ; x++)
1122                 {
1123                   val = *pf++ ;
1124                   if (val < fmin)
1125                     fmin = val ;
1126                   if (val > fmax)
1127                     fmax = val ;
1128                 }
1129             }
1130         }
1131       break ;
1132     case MRI_UCHAR:
1133       for (z = z0 ; z < depth ; z++)
1134         {
1135           for (y = y0 ; y < height ; y++)
1136             {
1137               pb = &MRIvox(mri, x0, y, z) ;
1138               for (x = x0 ; x < width ; x++)
1139                 {
1140                   val = (float)*pb++ ;
1141                   if (val < fmin)
1142                     fmin = val ;
1143                   if (val > fmax)
1144                     fmax = val ;
1145                 }
1146             }
1147         }
1148       break ;
1149     }
1150 
1151   *pmin = fmin ;
1152   *pmax = fmax ;
1153   return(NO_ERROR) ;
1154 }
1155 /*-----------------------------------------------------
1156   ------------------------------------------------------*/
1157 MRI_REGION *
1158 MRIclipRegion(MRI *mri, MRI_REGION *reg_src, MRI_REGION *reg_clip)
1159 {
1160   int  x2, y2, z2 ;
1161 
1162   x2 = MIN(mri->width-1, reg_src->x + reg_src->dx - 1) ;
1163   y2 = MIN(mri->height-1, reg_src->y + reg_src->dy - 1) ;
1164   z2 = MIN(mri->depth-1, reg_src->z + reg_src->dz - 1) ;
1165   reg_clip->x = MAX(0, reg_src->x) ;
1166   reg_clip->y = MAX(0, reg_src->y) ;
1167   reg_clip->z = MAX(0, reg_src->z) ;
1168   reg_clip->dx = x2 - reg_clip->x + 1 ;
1169   reg_clip->dy = y2 - reg_clip->y + 1 ;
1170   reg_clip->dz = z2 - reg_clip->z + 1 ;
1171   return(reg_clip) ;
1172 }
1173 /*-----------------------------------------------------
1174   ------------------------------------------------------*/
1175 MRI *
1176 MRIvalScale(MRI *mri_src, MRI *mri_dst, float flo, float fhi)
1177 {
1178   int      width, height, depth, x, y, z ;
1179   float    fmin, fmax, *pf_src, *pf_dst, val, scale ;
1180   short    *ps_src, *ps_dst ;
1181   BUFTYPE  *pb_src, *pb_dst ;
1182 
1183   if (!mri_dst)
1184     mri_dst = MRIclone(mri_src, NULL) ;
1185 
1186   MRIvalRange(mri_src, &fmin, &fmax) ;
1187   scale = (fhi - flo) / (fmax - fmin) ;
1188 
1189   width = mri_src->width ;
1190   height = mri_src->height ;
1191   depth = mri_src->depth ;
1192 
1193   switch (mri_src->type)
1194     {
1195     case MRI_FLOAT:
1196       for (z = 0 ; z < depth ; z++)
1197         {
1198           for (y = 0 ; y < height ; y++)
1199             {
1200               pf_src = &MRIFvox(mri_src, 0, y, z) ;
1201               pf_dst = &MRIFvox(mri_dst, 0, y, z) ;
1202               for (x = 0 ; x < width ; x++)
1203                 {
1204                   val = *pf_src++ ;
1205                   *pf_dst++ = (val - fmin) * scale + flo ;
1206                 }
1207             }
1208         }
1209       break ;
1210     case MRI_SHORT:
1211       for (z = 0 ; z < depth ; z++)
1212         {
1213           for (y = 0 ; y < height ; y++)
1214             {
1215               ps_src = &MRISvox(mri_src, 0, y, z) ;
1216               ps_dst = &MRISvox(mri_dst, 0, y, z) ;
1217               for (x = 0 ; x < width ; x++)
1218                 {
1219                   val = (float)(*ps_src++) ;
1220                   *ps_dst++ = (short)nint((val - fmin) * scale + flo) ;
1221                 }
1222             }
1223         }
1224       break ;
1225     case MRI_UCHAR:
1226       for (z = 0 ; z < depth ; z++)
1227         {
1228           for (y = 0 ; y < height ; y++)
1229             {
1230               pb_src = &MRIvox(mri_src, 0, y, z) ;
1231               pb_dst = &MRIvox(mri_dst, 0, y, z) ;
1232               for (x = 0 ; x < width ; x++)
1233                 {
1234                   val = (float)*pb_src++ ;
1235                   *pb_dst++ = (BUFTYPE)nint((val - fmin) * scale + flo) ;
1236                 }
1237             }
1238         }
1239       break ;
1240     default:
1241       ErrorReturn(mri_dst,
1242                   (ERROR_UNSUPPORTED, "MRIvalScale: unsupported type %d",
1243                    mri_src->type)) ;
1244     }
1245 
1246   return(mri_dst) ;
1247 }
1248 /*-----------------------------------------------------
1249   ------------------------------------------------------*/
1250 MRI *
1251 MRIconfThresh(MRI *mri_src, MRI *mri_probs, MRI *mri_classes, MRI *mri_dst,
1252               float thresh, int min_target, int max_target)
1253 {
1254   int      x, y, z, width, height, depth, class ;
1255   float    *pprobs, prob ;
1256   BUFTYPE  *pclasses, *pdst, *psrc, src ;
1257 
1258   if (!mri_dst)
1259     mri_dst = MRIclone(mri_classes, NULL) ;
1260 
1261   width = mri_classes->width ;
1262   height = mri_classes->height ;
1263   depth = mri_classes->depth ;
1264 
1265   for (z = 0 ; z < depth ; z++)
1266     {
1267       for (y = 0 ; y < height ; y++)
1268         {
1269           pprobs = &MRIFvox(mri_probs, 0, y, z) ;
1270           pclasses = &MRIvox(mri_classes, 0, y, z) ;
1271           pdst = &MRIvox(mri_dst, 0, y, z) ;
1272           psrc = &MRIvox(mri_src, 0, y, z) ;
1273           for (x = 0 ; x < width ; x++)
1274             {
1275               src = *psrc++ ;
1276               prob = *pprobs++ ;
1277               class = (int)*pclasses++ ;
1278               if (prob >= thresh &&
1279                   ((class >= min_target) && (class <= max_target)))
1280                 *pdst++ = src ;
1281               else if ((class >= min_target) && (class <= max_target))
1282                 *pdst++ = 25 ;
1283               else
1284                 *pdst++ = 0 ;
1285             }
1286         }
1287     }
1288   return(mri_dst) ;
1289 }
1290 /*-----------------------------------------------------
1291   ------------------------------------------------------*/
1292 int
1293 MRIboundingBoxNbhd(MRI *mri, int thresh, int wsize,MRI_REGION *box)
1294 {
1295   int      width, height, depth, x, y, z, x1, y1, z1, xi, yi, zi, xk, yk, zk,
1296     whalf, in_brain ;
1297   BUFTYPE  *psrc ;
1298   float    *pfsrc ;
1299   short    *pssrc ;
1300 
1301   whalf = (wsize-1)/2 ;
1302   box->dx = width = mri->width ;
1303   box->dy = height = mri->height ;
1304   box->dz = depth = mri->depth ;
1305 
1306   x1 = y1 = z1 = 0 ;
1307   box->x = width-1 ;
1308   box->y = height-1 ;
1309   box->z = depth-1 ;
1310   switch (mri->type)
1311     {
1312     case MRI_UCHAR:
1313       for (z = 0 ; z < depth ; z++)
1314         {
1315           for (y = 0 ; y < height ; y++)
1316             {
1317               psrc = &MRIvox(mri, 0, y, z) ;
1318               for (x = 0 ; x < width ; x++)
1319                 {
1320                   if (*psrc++ > thresh)
1321                     {
1322                       in_brain = 1 ;
1323                       for (zk = -whalf ; in_brain && zk <= whalf ; zk++)
1324                         {
1325                           zi = mri->zi[z+zk] ;
1326                           for (yk = -whalf ; in_brain && yk <= whalf ; yk++)
1327                             {
1328                               yi = mri->yi[y+yk] ;
1329                               for (xk = -whalf ;
1330                                    in_brain && xk <= whalf ;
1331                                    xk++)
1332                                 {
1333                                   xi = mri->xi[x+xk] ;
1334                                   if (MRIvox(mri, xi, yi, zi) < thresh)
1335                                     in_brain = 0 ;
1336                                 }
1337                             }
1338                         }
1339                       if (in_brain)
1340                         {
1341                           if (x < box->x)
1342                             box->x = x ;
1343                           if (y < box->y)
1344                             box->y = y ;
1345                           if (z < box->z)
1346                             box->z = z ;
1347                           if (x > x1)
1348                             x1 = x ;
1349                           if (y > y1)
1350                             y1 = y ;
1351                           if (z > z1)
1352                             z1 = z ;
1353                         }
1354                     }
1355                 }
1356             }
1357         }
1358       break ;
1359     case MRI_SHORT:
1360       for (z = 0 ; z < depth ; z++)
1361         {
1362           for (y = 0 ; y < height ; y++)
1363             {
1364               pssrc = &MRISvox(mri, 0, y, z) ;
1365               for (x = 0 ; x < width ; x++)
1366                 {
1367                   if (*pssrc++ > thresh)
1368                     {
1369                       in_brain = 1 ;
1370                       for (zk = -whalf ; in_brain && zk <= whalf ; zk++)
1371                         {
1372                           zi = mri->zi[z+zk] ;
1373                           for (yk = -whalf ; in_brain && yk <= whalf ; yk++)
1374                             {
1375                               yi = mri->yi[y+yk] ;
1376                               for (xk = -whalf ;
1377                                    in_brain && xk <= whalf ;
1378                                    xk++)
1379                                 {
1380                                   xi = mri->xi[x+xk] ;
1381                                   if (MRISvox(mri, xi, yi, zi) < thresh)
1382                                     in_brain = 0 ;
1383                                 }
1384                             }
1385                         }
1386                       if (in_brain)
1387                         {
1388                           if (x < box->x)
1389                             box->x = x ;
1390                           if (y < box->y)
1391                             box->y = y ;
1392                           if (z < box->z)
1393                             box->z = z ;
1394                           if (x > x1)
1395                             x1 = x ;
1396                           if (y > y1)
1397                             y1 = y ;
1398                           if (z > z1)
1399                             z1 = z ;
1400                         }
1401                     }
1402                 }
1403             }
1404         }
1405       break ;
1406     case MRI_FLOAT:
1407       for (z = 0 ; z < depth ; z++)
1408         {
1409           for (y = 0 ; y < height ; y++)
1410             {
1411               pfsrc = &MRIFvox(mri, 0, y, z) ;
1412               for (x = 0 ; x < width ; x++)
1413                 {
1414                   if (*pfsrc++ > thresh)
1415                     {
1416                       in_brain = 1 ;
1417                       for (zk = -whalf ; in_brain && zk <= whalf ; zk++)
1418                         {
1419                           zi = mri->zi[z+zk] ;
1420                           for (yk = -whalf ; in_brain && yk <= whalf ; yk++)
1421                             {
1422                               yi = mri->yi[y+yk] ;
1423                               for (xk = -whalf ;
1424                                    in_brain && xk <= whalf ;
1425                                    xk++)
1426                                 {
1427                                   xi = mri->xi[x+xk] ;
1428                                   if (MRIFvox(mri, xi, yi, zi) < thresh)
1429                                     in_brain = 0 ;
1430                                 }
1431                             }
1432                         }
1433                       if (in_brain)
1434                         {
1435                           if (x < box->x)
1436                             box->x = x ;
1437                           if (y < box->y)
1438                             box->y = y ;
1439                           if (z < box->z)
1440                             box->z = z ;
1441                           if (x > x1)
1442                             x1 = x ;
1443                           if (y > y1)
1444                             y1 = y ;
1445                           if (z > z1)
1446                             z1 = z ;
1447                         }
1448                     }
1449                 }
1450             }
1451         }
1452       break ;
1453     default:
1454       ErrorReturn(ERROR_UNSUPPORTED,
1455                   (ERROR_UNSUPPORTED, "MRIboundingBoxNbd: unsupported type %d",
1456                    mri->type)) ;
1457       break ;
1458     }
1459   box->x -= whalf+1 ; box->y -= whalf+1 ; box->z -= whalf+1 ;
1460   x1 += whalf+1 ; y1 += whalf+1 ; z1 += whalf+1 ;
1461   box->x = MAX(0,box->x) ; box->y = MAX(0,box->y) ; box->z = MAX(0,box->z) ;
1462   x1 = MIN(width-1,x1) ; y1 = MIN(height-1, y1) ; z1 = MIN(depth-1, z1) ;
1463   box->dx = x1 - box->x + 1 ;
1464   box->dy = y1 - box->y + 1 ;
1465   box->dz = z1 - box->z + 1 ;
1466   return(NO_ERROR) ;
1467 }
1468 /*-----------------------------------------------------
1469   ------------------------------------------------------*/
1470 #define MIN_DARK 10
1471 
1472 int
1473 MRIfindApproximateSkullBoundingBox(MRI *mri, int thresh,MRI_REGION *box)
1474 {
1475   int      width, height, depth, x, y, z, x1, y1, z1;
1476   int      ndark, max_dark, start, nlight, max_light ;
1477   double   means[3] ;
1478   Real     val ;
1479 
1480   width = mri->width ; height = mri->height ; depth = mri->depth ;
1481 
1482   MRIcenterOfMass(mri, means, thresh) ;
1483 
1484 
1485 #define MAX_LIGHT 30   /* don't let there by 3 cm of
1486                           bright stuff 'outside' of brain */
1487 
1488   /* search for left edge */
1489   nlight = ndark = max_dark = 0 ;
1490   y = nint(means[1]) ; z = nint(means[2]) ;
1491   for (start = x1 = x = nint(means[0]) ; x >= 0 ; x--)
1492     {
1493       MRIsampleVolumeType(mri, x,  y, z, &val, SAMPLE_NEAREST) ;
1494 
1495       if (val < thresh)
1496         {
1497           if (!ndark)
1498             start = x ;
1499           ndark++ ;
1500           nlight = 0  ;
1501         }
1502       else
1503         {
1504           if (++nlight > MAX_LIGHT)
1505             max_dark = 0 ;
1506           if (ndark > max_dark)
1507             {
1508               max_dark = ndark ; x1 = start ;
1509             }
1510           ndark = 0 ;
1511         }
1512     }
1513   if (ndark > max_dark)
1514     {
1515       max_dark = ndark ;
1516       x1 = start ;
1517     }
1518   if (max_dark < MIN_DARK)
1519     x1 = 0 ;
1520   box->x = x1 ;
1521 
1522   /* search for right edge */
1523   nlight = ndark = max_dark = 0 ;
1524   y = nint(means[1]) ; z = nint(means[2]) ;
1525   for (start = x1 = x = nint(means[0]) ; x < width ; x++)
1526     {
1527       MRIsampleVolumeType(mri, x,  y, z, &val, SAMPLE_NEAREST) ;
1528       if (val < thresh)
1529         {
1530           if (!ndark)
1531             start = x ;
1532           ndark++ ;
1533           nlight = 0 ;
1534         }
1535       else
1536         {
1537           if (++nlight > MAX_LIGHT)
1538             max_dark = 0 ;
1539           if (ndark >= max_dark)
1540             {
1541               max_dark = ndark ; x1 = start ;
1542             }
1543           ndark = 0 ;
1544         }
1545     }
1546   if (ndark > max_dark)
1547     {
1548       max_dark = ndark ;
1549       x1 = start ;
1550     }
1551   if (max_dark < MIN_DARK)
1552     x1 = mri->width-1 ;
1553   box->dx = x1 - box->x + 1 ;
1554 
1555   /* search for superior edge */
1556   nlight = ndark = max_dark = max_light = 0 ;
1557   x = MAX(0,nint(means[0])-20) ; // avoid inter-hemispheric fissure
1558   z = nint(means[2]) ;
1559   for (start = y1 = y = nint(means[1]) ; y >= 0 ; y--)
1560     {
1561       MRIsampleVolumeType(mri, x,  y, z, &val, SAMPLE_NEAREST) ;
1562       if (val < thresh)
1563         {
1564           if (nlight > max_light)
1565             max_light = nlight ;
1566           if (!ndark)
1567             start = y ;
1568           ndark++ ;
1569           nlight = 0 ;
1570         }
1571       else
1572         {
1573           if (++nlight > MAX_LIGHT)
1574             max_dark = 0 ;
1575           if (ndark >= max_dark)
1576             {
1577               max_dark = ndark ; y1 = start ;
1578               max_light = 0 ;  // max_light is max in a row light above dark
1579             }
1580           ndark = 0 ;
1581         }
1582     }
1583 
1584   /* if we ended on a string of dark voxels, check two things:
1585      1. the string was longer than the previous longest
1586      2. the strong was longer than 1/2 the previous longest, and there
1587      was an intervening string of light voxels indicated it was still in
1588      brain.
1589   */
1590   if ((ndark > max_dark) || (y < 0 &&
1591                              (ndark > max_dark/2) && max_light > MAX_LIGHT/2))
1592     {
1593       max_dark = ndark ;
1594       y1 = start ;
1595     }
1596   if (max_dark < MIN_DARK)
1597     y1 = 0 ;
1598   box->y = y1 ;
1599 
1600   /* search for inferior edge */
1601   nlight = ndark = max_dark = 0 ;
1602   x = nint(means[0]) ; z = nint(means[2]) ;
1603   for (start = y = y1 = nint(means[1]) ; y < height ; y++)
1604     {
1605       MRIsampleVolumeType(mri, x,  y, z, &val, SAMPLE_NEAREST) ;
1606       if (val < thresh)
1607         {
1608           if (!ndark)
1609             start = y ;
1610           ndark++ ;
1611           nlight = 0 ;
1612         }
1613       else
1614         {
1615           if (++nlight > MAX_LIGHT)
1616             max_dark = 0 ;
1617           if (ndark >= max_dark)
1618             {
1619               max_dark = ndark ; y1 = start ;
1620             }
1621           ndark = 0 ;
1622         }
1623     }
1624   if (ndark > max_dark)
1625     {
1626       max_dark = ndark ;
1627       y1 = start ;
1628     }
1629   if (max_dark < MIN_DARK)
1630     y1 = mri->height-1 ;
1631   box->dy = y1 - box->y + 1 ;
1632 
1633   /* search for posterior edge */
1634   nlight = ndark = max_dark = 0 ;
1635   x = nint(means[0]) ; y = nint(means[1]) ;
1636   for (z1 = start = z = nint(means[2]) ; z >= 0 ; z--)
1637     {
1638       MRIsampleVolumeType(mri, x,  y, z, &val, SAMPLE_NEAREST) ;
1639       if (val < thresh)
1640         {
1641           if (!ndark)
1642             start = z ;
1643           ndark++ ;
1644           nlight = 0 ;
1645         }
1646       else
1647         {
1648           if (++nlight > MAX_LIGHT)
1649             max_dark = 0 ;
1650           if (ndark >= max_dark)
1651             {
1652               max_dark = ndark ; z1 = start ;
1653             }
1654           ndark = 0 ;
1655         }
1656     }
1657   if (ndark > max_dark)
1658     {
1659       max_dark = ndark ;
1660       z1 = start ;
1661     }
1662   if (max_dark < MIN_DARK)
1663     z1 = 0 ;
1664   box->z = z1 ;
1665 
1666   /* search for anterior edge */
1667   nlight = ndark = max_dark = 0 ;
1668   x = nint(means[0]) ; y = nint(means[1]) ;
1669   for (start = z = nint(means[2]) ; z < depth ; z++)
1670     {
1671       MRIsampleVolumeType(mri, x,  y, z, &val, SAMPLE_NEAREST) ;
1672       if (val < thresh)
1673         {
1674           if (!ndark)
1675             start = z ;
1676           ndark++ ;
1677           nlight = 0 ;
1678         }
1679       else
1680         {
1681           if (++nlight > MAX_LIGHT)
1682             max_dark = 0 ;
1683           if (ndark >= max_dark)
1684             {
1685               max_dark = ndark ; z1 = start ;
1686             }
1687           ndark = 0 ;
1688         }
1689     }
1690   if (ndark > max_dark)
1691     {
1692       max_dark = ndark ;
1693       z1 = start ;
1694     }
1695   if (max_dark < MIN_DARK)
1696     z1 = mri->depth-1 ;
1697   box->dz = z1 - box->z + 1 ;
1698 
1699   return(NO_ERROR) ;
1700 }
1701 /*-----------------------------------------------------
1702   ------------------------------------------------------*/
1703 int
1704 MRIboundingBox(MRI *mri, int thresh, MRI_REGION *box)
1705 {
1706   int      width, height, depth, x, y, z, x1, y1, z1 ;
1707   BUFTYPE  *psrc ;
1708   float    *pfsrc ;
1709   short    *pssrc ;
1710 
1711   box->dx = width = mri->width ;
1712   box->dy = height = mri->height ;
1713   box->dz = depth = mri->depth ;
1714 
1715   x1 = y1 = z1 = 0 ;
1716   box->x = width-1 ;
1717   box->y = height-1 ;
1718   box->z = depth-1 ;
1719   switch (mri->type)
1720     {
1721     case MRI_UCHAR:
1722       for (z = 0 ; z < depth ; z++)
1723         {
1724           for (y = 0 ; y < height ; y++)
1725             {
1726               psrc = &MRIvox(mri, 0, y, z) ;
1727               for (x = 0 ; x < width ; x++)
1728                 {
1729                   if (*psrc++ > thresh)
1730                     {
1731                       if (x < box->x)
1732                         box->x = x ;
1733                       if (y < box->y)
1734                         box->y = y ;
1735                       if (z < box->z)
1736                         box->z = z ;
1737                       if (x > x1)
1738                         x1 = x ;
1739                       if (y > y1)
1740                         y1 = y ;
1741                       if (z > z1)
1742                         z1 = z ;
1743                     }
1744                 }
1745             }
1746         }
1747       break ;
1748     case MRI_FLOAT:
1749       for (z = 0 ; z < depth ; z++)
1750         {
1751           for (y = 0 ; y < height ; y++)
1752             {
1753               pfsrc = &MRIFvox(mri, 0, y, z) ;
1754               for (x = 0 ; x < width ; x++)
1755                 {
1756                   if (*pfsrc++ > thresh)
1757                     {
1758                       if (x < box->x)
1759                         box->x = x ;
1760                       if (y < box->y)
1761                         box->y = y ;
1762                       if (z < box->z)
1763                         box->z = z ;
1764                       if (x > x1)
1765                         x1 = x ;
1766                       if (y > y1)
1767                         y1 = y ;
1768                       if (z > z1)
1769                         z1 = z ;
1770                     }
1771                 }
1772             }
1773         }
1774       break ;
1775     case MRI_SHORT:
1776       for (z = 0 ; z < depth ; z++)
1777         {
1778           for (y = 0 ; y < height ; y++)
1779             {
1780               pssrc = &MRISvox(mri, 0, y, z) ;
1781               for (x = 0 ; x < width ; x++)
1782                 {
1783                   if (*pssrc++ > thresh)
1784                     {
1785                       if (x < box->x)
1786                         box->x = x ;
1787                       if (y < box->y)
1788                         box->y = y ;
1789                       if (z < box->z)
1790                         box->z = z ;
1791                       if (x > x1)
1792                         x1 = x ;
1793                       if (y > y1)
1794                         y1 = y ;
1795                       if (z > z1)
1796                         z1 = z ;
1797                     }
1798                 }
1799             }
1800         }
1801       break ;
1802     default:
1803       ErrorReturn(ERROR_UNSUPPORTED,
1804                   (ERROR_UNSUPPORTED, "MRIboundingBox: unsupported type %d",
1805                    mri->type)) ;
1806       break ;
1807     }
1808   box->dx = x1 - box->x + 1 ;
1809   box->dy = y1 - box->y + 1 ;
1810   box->dz = z1 - box->z + 1 ;
1811   return(NO_ERROR) ;
1812 }
1813 /*-----------------------------------------------------
1814   ------------------------------------------------------*/
1815 int
1816 MRIcheckSize(MRI *mri_src, MRI *mri_check, int width, int height, int depth)
1817 {
1818   if (!mri_check)
1819     return(0) ;
1820 
1821   if (!width)
1822     width = mri_src->width ;
1823   if (!height)
1824     height = mri_src->height ;
1825   if (!depth)
1826     depth = mri_src->depth ;
1827 
1828   if (width != mri_check->width ||
1829       height != mri_check->height ||
1830       depth != mri_check->depth)
1831     return(0) ;
1832 
1833   return(1) ;
1834 }
1835 /*-----------------------------------------------------
1836   ------------------------------------------------------*/
1837 int
1838 MRItransformRegion(MRI *mri_src, MRI *mri_dst, MRI_REGION *src_region,
1839                    MRI_REGION *dst_region)
1840 {
1841   Real  xw, yw, zw, xt, yt, zt, xv, yv, zv ;
1842 
1843   if (getSliceDirection(mri_src) != getSliceDirection(mri_dst))
1844     ErrorReturn(ERROR_UNSUPPORTED,
1845                 (ERROR_UNSUPPORTED,
1846                  "MRItransformRegion(%s): slice directions must match",
1847                  mri_src->fname)) ;
1848 
1849   if (!mri_src->linear_transform)
1850     ErrorReturn(ERROR_UNSUPPORTED,
1851                 (ERROR_UNSUPPORTED,
1852                  "MRItransformRegion(%s): no transform loaded",
1853                  mri_src->fname)) ;
1854   if (!mri_dst->linear_transform)
1855     ErrorReturn(ERROR_UNSUPPORTED,
1856                 (ERROR_UNSUPPORTED,
1857                  "MRItransformRegion(%s): no transform loaded",
1858                  mri_dst->fname)) ;
1859   /*
1860     The convention  is  that  positive xspace coordinates run
1861     from the patient's  left  side  to  right  side,  positive
1862     yspace  coordinates run from patient posterior to anterior
1863     and positive zspace coordinates run from inferior to superior.
1864   */
1865   switch (getSliceDirection(mri_src))
1866     {
1867     case MRI_CORONAL:
1868       break ;
1869     default:
1870       ErrorReturn
1871         (ERROR_UNSUPPORTED,
1872          (ERROR_UNSUPPORTED,
1873           "MRIregionToTalairachRegion: unsupported slice direction %d",
1874           getSliceDirection(mri_src))) ;
1875     }
1876 
1877   xv = (Real)src_region->x ;
1878   yv = (Real)src_region->y ;
1879   zv = (Real)src_region->z ;
1880   MRIvoxelToWorld(mri_src, xv, yv, zv, &xw, &yw, &zw) ;
1881   transform_point(mri_src->linear_transform, xw, yw, zw, &xt, &yt, &zt) ;
1882   transform_point(mri_dst->inverse_linear_transform, xt, yt, zt, &xw,&yw,&zw);
1883   MRIworldToVoxel(mri_dst, xw, yw, zw, &xv, &yv, &zv) ;
1884   dst_region->x = nint(xv) ;
1885   dst_region->y = nint(yv) ;
1886   dst_region->z = nint(zv) ;
1887 
1888   xv = (Real)(src_region->x + src_region->dx - 1) ;
1889   yv = (Real)(src_region->y + src_region->dy - 1) ;
1890   zv = (Real)(src_region->z + src_region->dz - 1) ;
1891   MRIvoxelToWorld(mri_src, xv, yv, zv, &xw, &yw, &zw) ;
1892   transform_point(mri_src->linear_transform, xw, yw, zw, &xt, &yt, &zt) ;
1893   transform_point(mri_dst->inverse_linear_transform, xt, yt, zt, &xw,&yw,&zw);
1894   MRIworldToVoxel(mri_dst, xw, yw, zw, &xv, &yv, &zv) ;
1895   dst_region->dx = nint(xv - (Real)dst_region->x) + 1 ;
1896   dst_region->dy = nint(yv - (Real)dst_region->y) + 1 ;
1897   dst_region->dz = nint(zv - (Real)dst_region->z) + 1 ;
1898 
1899   return(NO_ERROR) ;
1900 }
1901 /*-----------------------------------------------------
1902   ------------------------------------------------------*/
1903 int
1904 MRIvoxelToVoxel(MRI *mri_src, MRI *mri_dst, Real xv, Real yv, Real zv,
1905                 Real *pxt, Real *pyt, Real *pzt)
1906 {
1907   Real  xw, yw, zw, xt, yt, zt ;
1908 
1909 #if 0
1910   if (!mri_src->linear_transform)
1911     ErrorReturn(ERROR_UNSUPPORTED,
1912                 (ERROR_UNSUPPORTED,
1913                  "MRIvoxelToVoxel(%s): no transform loaded", mri_src->fname));
1914 #endif
1915 
1916   /*
1917     The convention  is  that  positive xspace coordinates run
1918     from the patient's  left  side  to  right  side,  positive
1919     yspace  coordinates run from patient posterior to anterior
1920     and positive zspace coordinates run from inferior to superior.
1921   */
1922   switch (getSliceDirection(mri_src))
1923     {
1924     case MRI_CORONAL:
1925       break ;
1926     default:
1927       ErrorReturn(ERROR_UNSUPPORTED,
1928                   (ERROR_UNSUPPORTED,
1929                    "MRIvoxelToVoxel: unsupported slice direction %d",
1930                    getSliceDirection(mri_src))) ;
1931     }
1932 
1933   if (!mri_src->linear_transform || !mri_dst->inverse_linear_transform)
1934     {
1935       /*
1936          if either doesn't have a transform defined, assume they are in
1937          the same coordinate system.
1938       */
1939       *pxt = xv ; *pyt = yv ; *pzt = zv ;
1940     }
1941   else
1942     {
1943       MRIvoxelToWorld(mri_src, xv, yv, zv, &xw, &yw, &zw) ;
1944       if (mri_src->linear_transform)
1945         transform_point(mri_src->linear_transform, xw, yw, zw, &xt, &yt, &zt) ;
1946       else
1947         {
1948           xt = xw ; yt = yw ; zt = zw ;
1949         }
1950       if (mri_dst->inverse_linear_transform)
1951         transform_point
1952           (mri_dst->inverse_linear_transform, xt,yt,zt,&xw,&yw,&zw);
1953       else
1954         {
1955           xw = xt ; yw = yt ; zw = zt ;
1956         }
1957       MRIworldToVoxel(mri_dst, xw, yw, zw, pxt, pyt, pzt) ;
1958     }
1959 
1960   return(NO_ERROR) ;
1961 }
1962 /*-----------------------------------------------------
1963   ------------------------------------------------------*/
1964 int
1965 MRIvoxelToTalairachVoxel(MRI *mri, Real xv, Real yv, Real zv,
1966                          Real *pxt, Real *pyt, Real *pzt)
1967 {
1968   Real  xw, yw, zw, xt, yt, zt ;
1969 
1970 #if 0
1971   if (!mri->linear_transform)
1972     ErrorReturn(ERROR_UNSUPPORTED,
1973                 (ERROR_UNSUPPORTED,
1974                  "MRIvoxelToTalairachVoxel(%s): no transform loaded",
1975                  mri->fname)) ;
1976 #endif
1977   /*
1978     The convention  is  that  positive xspace coordinates run
1979     from the patient's  left  side  to  right  side,  positive
1980     yspace  coordinates run from patient posterior to anterior
1981     and positive zspace coordinates run from inferior to superior.
1982   */
1983   switch (getSliceDirection(mri))
1984     {
1985     case MRI_CORONAL:
1986       break ;
1987     default:
1988       ErrorReturn(ERROR_UNSUPPORTED,
1989                   (ERROR_UNSUPPORTED,
1990                    "MRIvoxelToTalairachVoxel: unsupported slice direction %d",
1991                    getSliceDirection(mri))) ;
1992     }
1993 
1994   MRIvoxelToWorld(mri, xv, yv, zv, &xw, &yw, &zw) ;
1995   if (mri->linear_transform)
1996     transform_point(mri->linear_transform, xw, yw, zw, &xt, &yt, &zt) ;
1997   else
1998     { xt = xw ; yt = yw ; zt = zw ; }
1999   MRIworldToVoxel(mri, xt, yt, zt, pxt, pyt, pzt) ;
2000 
2001   return(NO_ERROR) ;
2002 }
2003 /*-----------------------------------------------------
2004   ------------------------------------------------------*/
2005 int
2006 MRIvoxelToTalairach(MRI *mri, Real xv, Real yv, Real zv,
2007                     Real *pxt, Real *pyt, Real *pzt)
2008 {
2009   Real  xw, yw, zw ;
2010 
2011 #if 0
2012   if (!mri->linear_transform)
2013     ErrorReturn(ERROR_UNSUPPORTED,
2014                 (ERROR_UNSUPPORTED,
2015                  "MRIvoxelToTalairachVoxel(%s): no transform loaded",
2016                  mri->fname)) ;
2017 #endif
2018 
2019   /*
2020     The convention  is  that  positive xspace coordinates run
2021     from the patient's  left  side  to  right  side,  positive
2022     yspace  coordinates run from patient posterior to anterior
2023     and positive zspace coordinates run from inferior to superior.
2024   */
2025   switch (getSliceDirection(mri))
2026     {
2027     case MRI_CORONAL:
2028       break ;
2029     default:
2030       ErrorReturn(ERROR_UNSUPPORTED,
2031                   (ERROR_UNSUPPORTED,
2032                    "MRIvoxelToTalairachVoxel: unsupported slice direction %d",
2033                    getSliceDirection(mri))) ;
2034     }
2035 
2036   MRIvoxelToWorld(mri, xv, yv, zv, &xw, &yw, &zw) ;
2037   if (mri->linear_transform)
2038     transform_point(mri->linear_transform, xw, yw, zw, pxt, pyt, pzt) ;
2039   else
2040     { *pxt = xw ; *pyt = yw ; *pzt = zw ; }
2041 
2042   return(NO_ERROR) ;
2043 }
2044 /*-----------------------------------------------------
2045   ------------------------------------------------------*/
2046 int
2047 MRItalairachToVoxel(MRI *mri, Real xt, Real yt, Real zt,
2048                     Real *pxv, Real *pyv, Real *pzv)
2049 {
2050   Real  xw, yw, zw ;
2051 
2052 #if 0
2053   if (!mri->inverse_linear_transform)
2054     ErrorReturn(ERROR_UNSUPPORTED,
2055                 (ERROR_UNSUPPORTED,
2056                  "MRItalairachToVoxel(%s): no transform loaded",
2057                  mri->fname)) ;
2058 #endif
2059 
2060   /*
2061     The convention  is  that  positive xspace coordinates run
2062     from the patient's  left  side  to  right  side,  positive
2063     yspace  coordinates run from patient posterior to anterior
2064     and positive zspace coordinates run from inferior to superior.
2065   */
2066   switch (getSliceDirection(mri))
2067     {
2068     case MRI_CORONAL:
2069       break ;
2070     default:
2071       ErrorReturn(ERROR_UNSUPPORTED,
2072                   (ERROR_UNSUPPORTED,
2073                    "MRIvoxelToTalairachVoxel: unsupported slice direction %d",
2074                    getSliceDirection(mri))) ;
2075     }
2076 
2077   if (mri->inverse_linear_transform)
2078     transform_point(mri->inverse_linear_transform, xt, yt, zt, &xw, &yw,&zw);
2079   else
2080     { xw = xt ; yw = yt ; zw = zt ; }
2081   MRIworldToVoxel(mri, xw, yw, zw, pxv, pyv, pzv) ;
2082 
2083   return(NO_ERROR) ;
2084 }
2085 /*-----------------------------------------------------
2086   ------------------------------------------------------*/
2087 int
2088 MRItalairachVoxelToVoxel(MRI *mri, Real xtv, Real ytv, Real ztv,
2089                          Real *pxv, Real *pyv, Real *pzv)
2090 {
2091   Real  xw, yw, zw, xt, yt, zt ;
2092 
2093 #if 0
2094   if (!mri->inverse_linear_transform)
2095     ErrorReturn(ERROR_UNSUPPORTED,
2096                 (ERROR_UNSUPPORTED,
2097                  "MRItalairachVoxelToVoxel(%s): no transform loaded",
2098                  mri->fname)) ;
2099 #endif
2100 
2101   /*
2102     The convention  is  that  positive xspace coordinates run
2103     from the patient's  left  side  to  right  side,  positive
2104     yspace  coordinates run from patient posterior to anterior
2105     and positive zspace coordinates run from inferior to superior.
2106   */
2107   switch (getSliceDirection(mri))
2108     {
2109     case MRI_CORONAL:
2110       break ;
2111     default:
2112       ErrorReturn(ERROR_UNSUPPORTED,
2113                   (ERROR_UNSUPPORTED,
2114                    "MRIvoxelToTalairachVoxel: unsupported slice direction %d",
2115                    getSliceDirection(mri))) ;
2116     }
2117 
2118   MRIvoxelToWorld(mri, xtv, ytv, ztv, &xt, &yt, &zt) ;
2119   if (mri->inverse_linear_transform)
2120     transform_point(mri->inverse_linear_transform, xt, yt, zt, &xw, &yw,&zw);
2121   else
2122     { xw = xt ; yw = yt ; zw = zt ; }
2123   MRIworldToVoxel(mri, xw, yw, zw, pxv, pyv, pzv) ;
2124 
2125   return(NO_ERROR) ;
2126 }
2127 /*-----------------------------------------------------
2128   ------------------------------------------------------*/
2129 int
2130 MRItalairachVoxelToWorld(MRI *mri, Real xtv, Real ytv, Real ztv,
2131                          Real *pxw, Real *pyw, Real *pzw)
2132 {
2133   Real  xw, yw, zw, xt, yt, zt ;
2134 
2135 #if 0
2136   if (!mri->inverse_linear_transform)
2137     ErrorReturn(ERROR_UNSUPPORTED,
2138                 (ERROR_UNSUPPORTED,
2139                  "MRItalairachVoxelToVoxel(%s): no transform loaded",
2140                  mri->fname)) ;
2141 #endif
2142 
2143   /*
2144     The convention  is  that  positive xspace coordinates run
2145     from the patient's  left  side  to  right  side,  positive
2146     yspace  coordinates run from patient posterior to anterior
2147     and positive zspace coordinates run from inferior to superior.
2148   */
2149   switch (getSliceDirection(mri))
2150     {
2151     case MRI_CORONAL:
2152       break ;
2153     default:
2154       ErrorReturn(ERROR_UNSUPPORTED,
2155                   (ERROR_UNSUPPORTED,
2156                    "MRIvoxelToTalairachVoxel: unsupported slice direction %d",
2157                    getSliceDirection(mri))) ;
2158     }
2159 
2160   MRIvoxelToWorld(mri, xtv, ytv, ztv, &xt, &yt, &zt) ;
2161   if (mri->inverse_linear_transform)
2162     transform_point(mri->inverse_linear_transform, xt, yt, zt, &xw, &yw,&zw);
2163   else
2164     { xw = xt ; yw = yt ; zw = zt ; }
2165   *pxw = xw ; *pyw = yw ; *pzw = zw ;
2166 
2167   return(NO_ERROR) ;
2168 }
2169 /*-----------------------------------------------------
2170   ------------------------------------------------------*/
2171 #define V4_LOAD(v, x, y, z, r)  (VECTOR_ELT(v,1)=x, VECTOR_ELT(v,2)=y, \
$^
                                  VECTOR_ELT(v,3)=z, VECTOR_ELT(v,4)=r) ;
2172 
2173 int
2174 MRIvoxelToWorld(MRI *mri, Real xv, Real yv, Real zv,
2175                 Real *pxw, Real *pyw, Real *pzw)
2176 {
2177   VECTOR *vw, *vv;
2178   MATRIX *RfromI;
2179 
2180   // if the transform is not cached yet, then
2181   if (!mri->i_to_r__)
2182     mri->i_to_r__ = extract_i_to_r(mri);
2183   if (!mri->r_to_i__)
2184     mri->r_to_i__ = extract_r_to_i(mri);
2185 
2186   RfromI = mri->i_to_r__; // extract_i_to_r(mri);
2187 
2188   vv = VectorAlloc(4, MATRIX_REAL) ;
2189   V4_LOAD(vv, xv, yv, zv, 1.) ;
2190   vw = MatrixMultiply(RfromI, vv, NULL) ;
2191   *pxw = V3_X(vw);
2192   *pyw = V3_Y(vw);
2193   *pzw = V3_Z(vw);
2194 
2195   // MatrixFree(&RfromI);
2196   VectorFree(&vv);
2197   VectorFree(&vw);
2198   return(NO_ERROR) ;
2199 }
2200 /*-----------------------------------------------------
2201   ------------------------------------------------------*/
2202 int
2203 MRIworldToTalairachVoxel(MRI *mri, Real xw, Real yw, Real zw,
2204                          Real *pxv, Real *pyv, Real *pzv)
2205 {
2206   Real  xt, yt, zt ;
2207 
2208   transform_point(mri->linear_transform, xw, yw, zw, &xt, &yt, &zt) ;
2209   MRIworldToVoxel(mri, xt, yt, zt, pxv, pyv, pzv) ;
2210   return(NO_ERROR) ;
2211 }
2212 /*-----------------------------------------------------
2213   ------------------------------------------------------*/
2214 int MRIworldToVoxelIndex(MRI *mri, Real xw, Real yw, Real zw,
2215                          int *pxv, int *pyv, int *pzv)
2216 {
2217   Real xv, yv, zv;
2218   MRIworldToVoxel(mri, xw, yw, zw, &xv, &yv, &zv);
2219   *pxv = (int) xv;
2220   *pyv = (int) yv;
2221   *pzv = (int) zv;
2222 
2223   /*
2224     switch (getSliceDirection(mri))
2225     {
2226     case MRI_CORONAL:
2227     #if 0
2228     *pxv = ((Real)mri->xend - xw) / mri->xsize ;
2229     *pzv = (yw - (Real)mri->zstart) / mri->zsize ;
2230     *pyv = (-zw - (Real)mri->ystart) / mri->ysize ;
2231     #else
2232     trans_SetBounds ( mri->xstart, mri->xend, mri->ystart, mri->yend,
2233     mri->zstart, mri->zend );
2234     trans_SetResolution ( mri->xsize, mri->ysize, mri->zsize );
2235     trans_RASToVoxelIndex(xw, yw, zw, pxv, pyv, pzv) ;
2236     #endif
2237     break ;
2238     default:
2239     ErrorReturn(ERROR_UNSUPPORTED,
2240     (ERROR_UNSUPPORTED,
2241     "MRIworldToVoxel: unsupported slice direction %d",
2242     getSliceDirection(mri))) ;
2243     break ;
2244     }
2245   */
2246   return(NO_ERROR) ;
2247 }
2248 
2249 /*
2250    int MRIvoxelToSurfaceRAS and int MRIsurfaceRASToVoxel
2251 
2252    get the surfaceRAS values from original voxel
2253    Note that this is different from MRIvoxelToWorld().
2254 
2255    Note that currently MATRIX uses float** to store data.
2256    Going around the circle of transform causes error accumulation quickly.
2257    I noticed that 7 x 10^(-6) is very common.
2258 
2259 */
2260 
2261 MATRIX *surfaceRASFromVoxel_(MRI *mri)
2262 {
2263   // Derivation (avoid expensive matrix calculation)
2264   //
2265   //     orig -----(rasFromVoxel)------> RAS (scanner RAS or physical RAS)
2266   //       |                              |
2267   //(conformedVoxelFromVoxel)            (1)
2268   //       |                              |
2269   //       V                              V
2270   //conformed--(RASfromConformed)----->RAS (scanner RAS or physical RAS)
2271   //       |                              |
2272   //      (1)                      (surfaceRASFromRAS)
2273   //       |                              |
2274   //       V                              V
2275   //conformed-(surfaceRASFromConformed)->surfaceRAS
2276   //
2277   //
2278   // where  RASFromConformed = [ -1  0  0   s1 ] where s1 = c_r + 128
2279   //                           [  0  0  1   s2 ]       s2 = c_a - 128
2280   //                           [  0 -1  0   s3 ]       s3 = c_s + 128
2281   //                           [  0  0  0    1 ]
2282   //
2283   //  surfaceRASFromConformed= [ -1  0  0  128 ]
2284   //                           [  0  0  1 -128 ]
2285   //                           [  0 -1  0  128 ]
2286   //                           [  0  0  0   1  ]
2287   // Therefore
2288   //        surfaceRASFromRAS= [  1  0  0  -c_r]  just a translation matrix
2289   //                           [  0  1  0  -c_a]
2290   //                           [  0  0  1  -c_s]
2291   //                           [  0  0  0    1 ]
2292   //
2293   //  surfaceRASFromVoxel = surfaceRASFromRAS (x) rasFromVoxel
2294   //
2295   //  i.e.       applying translation on RASFromVoxel
2296   //
2297   // This means tha
2298   //
2299   //  if RASFromVoxel = (  X  | T ), then
2300   //                    (  0  | 1 )
2301   //
2302   //    surfaceRASFromVoxel =  ( 1 | -C) * ( X | T ) = ( X | T - C )
2303   //                           ( 0 | 1 )   ( 0 | 1 )   ( 0 |   1   )
2304   //
2305   MATRIX *rasFromVoxel;
2306   MATRIX *sRASFromVoxel;
2307   double m14, m24, m34;
2308 
2309   // if the transform is not cached yet, then
2310   if (!mri->i_to_r__)
2311     mri->i_to_r__ = extract_i_to_r(mri);
2312   if (!mri->r_to_i__)
2313     mri->r_to_i__ = extract_r_to_i(mri);
2314 
2315   rasFromVoxel = mri->i_to_r__; // extract_i_to_r(mri);
2316 
2317   sRASFromVoxel = MatrixCopy(rasFromVoxel, NULL);
2318   // MatrixFree(&rasFromVoxel);
2319   // modify
2320   m14 = *MATRIX_RELT(sRASFromVoxel, 1,4);
2321   *MATRIX_RELT(sRASFromVoxel, 1,4) = m14 - mri->c_r;
2322   m24 = *MATRIX_RELT(sRASFromVoxel, 2,4);
2323   *MATRIX_RELT(sRASFromVoxel, 2,4) = m24 - mri->c_a;
2324   m34 = *MATRIX_RELT(sRASFromVoxel, 3,4);
2325   *MATRIX_RELT(sRASFromVoxel, 3,4) = m34 - mri->c_s;
2326 
2327   return sRASFromVoxel;
2328 }
2329 
2330 MATRIX *surfaceRASFromRAS_(MRI *mri)
2331 {
2332   MATRIX *sRASFromRAS;
2333   sRASFromRAS = MatrixAlloc(4, 4, MATRIX_REAL);
2334   MatrixIdentity(4, sRASFromRAS);
2335   *MATRIX_RELT(sRASFromRAS, 1,4) = - mri->c_r;
2336   *MATRIX_RELT(sRASFromRAS, 2,4) = - mri->c_a;
2337   *MATRIX_RELT(sRASFromRAS, 3,4) = - mri->c_s;
2338   return sRASFromRAS;
2339 }
2340 
2341 MATRIX *RASFromSurfaceRAS_(MRI *mri)
2342 {
2343   MATRIX *RASFromSRAS;
2344   RASFromSRAS = MatrixAlloc(4, 4, MATRIX_REAL);
2345   MatrixIdentity(4, RASFromSRAS);
2346   *MATRIX_RELT(RASFromSRAS, 1,4) = mri->c_r;
2347   *MATRIX_RELT(RASFromSRAS, 2,4) = mri->c_a;
2348   *MATRIX_RELT(RASFromSRAS, 3,4) = mri->c_s;
2349   return RASFromSRAS;
2350 }
2351 
2352 int MRIRASToSurfaceRAS(MRI *mri, Real xr, Real yr, Real zr,
2353                        Real *xsr, Real *ysr, Real *zsr)
2354 {
2355   MATRIX *surfaceRASFromRAS=0;
2356   VECTOR *v, *sr;
2357   v = VectorAlloc(4, MATRIX_REAL);
2358   V4_LOAD(v, xr, yr, zr, 1.);
2359   surfaceRASFromRAS = surfaceRASFromRAS_(mri);
2360   sr = MatrixMultiply(surfaceRASFromRAS, v, NULL);
2361   *xsr = V3_X(sr);
2362   *ysr = V3_Y(sr);
2363   *zsr = V3_Z(sr);
2364   MatrixFree(&surfaceRASFromRAS);
2365   VectorFree(&v);
2366   VectorFree(&sr);
2367   return (NO_ERROR);
2368 }
2369 
2370 int MRIsurfaceRASToRAS(MRI *mri, Real xsr, Real ysr, Real zsr,
2371                        Real *xr, Real *yr, Real *zr)
2372 {
2373   MATRIX *RASFromSurfaceRAS=0;
2374   VECTOR *v, *r;
2375   v = VectorAlloc(4, MATRIX_REAL);
2376   V4_LOAD(v, xsr, ysr, zsr, 1.);
2377   RASFromSurfaceRAS = RASFromSurfaceRAS_(mri);
2378   r = MatrixMultiply(RASFromSurfaceRAS, v, NULL);
2379   *xr = V3_X(r);
2380   *yr = V3_Y(r);
2381   *zr = V3_Z(r);
2382   MatrixFree(&RASFromSurfaceRAS);
2383   VectorFree(&v);
2384   VectorFree(&r);
2385   return (NO_ERROR);
2386 }
2387 
2388 
2389 int MRIvoxelToSurfaceRAS(MRI *mri, Real xv, Real yv, Real zv,
2390                          Real *xs, Real *ys, Real *zs)
2391 {
2392   MATRIX *sRASFromVoxel;
2393   VECTOR *vv, *sr;
2394 
2395   sRASFromVoxel = surfaceRASFromVoxel_(mri);
2396   // calculate the surface ras value
2397   vv = VectorAlloc(4, MATRIX_REAL);
2398   V4_LOAD(vv, xv, yv, zv, 1.);
2399   sr = MatrixMultiply(sRASFromVoxel, vv, NULL);
2400   *xs = V3_X(sr);
2401   *ys = V3_Y(sr);
2402   *zs = V3_Z(sr);
2403 
2404   MatrixFree(&sRASFromVoxel);
2405   VectorFree(&vv);
2406   VectorFree(&sr);
2407 
2408   return (NO_ERROR);
2409 }
2410 
2411 MATRIX *voxelFromSurfaceRAS_(MRI *mri)
2412 {
2413   MATRIX *voxelFromSRAS =0;
2414   //////////////////////////////////////////////////////////////////
2415   // it turned out that this can be done easily without taking inverse
2416   // Note the surfaceRASFromVoxel_ is given by
2417   //
2418   //       ( X | T - C)
2419   //       ( 0 |  1   )
2420   // Note, however, that we define C by
2421   //
2422   //      (  X | T ) (S/2) = ( C )  where S = (w/2, h/2, d/2)^t
2423   //      (  0 | 1 ) ( 1 )   ( 1 )
2424   // Thus
2425   //        X*S/2 + T = C
2426   // or
2427   //        T - C = - X*S/2
2428   // or
2429   //     surfaceRASFromVoxel = ( X | - X*S/2 )
2430   //                           ( 0 |    1    )
2431   // whose inverse is given by
2432   //
2433   //     voxelFromSurfaceRAS = ( X ^(-1)| S/2 )
2434   //                           (  0     |  1  )
2435   //
2436   // since
2437   //           ( X^(-1)  S/2) ( X  -X*S/2) = ( 1   S/2 - S/2) = 1
2438   //           (   0      1 ) ( 0     1  )   ( 0      1     )
2439   //
2440   // thus get r_to_i__ and set translation part to S/2 is the quickest way
2441   /////////////////////////////////////////////////////////////////////
2442   // if the transform is not cached yet, then
2443   if (!mri->i_to_r__)
2444     mri->i_to_r__ = extract_i_to_r(mri);
2445   if (!mri->r_to_i__)
2446     mri->r_to_i__ = extract_r_to_i(mri);
2447 
2448   voxelFromSRAS = MatrixCopy(mri->r_to_i__, NULL);
2449   // modify translation part
2450   *MATRIX_RELT(voxelFromSRAS, 1,4) = mri->width/2;
2451   *MATRIX_RELT(voxelFromSRAS, 2,4) = mri->height/2;
2452   *MATRIX_RELT(voxelFromSRAS, 3,4) = mri->depth/2;
2453 
2454 #if 0
2455   // no more expensive inverse
2456   MATRIX *sRASFromVoxel = surfaceRASFromVoxel_(mri);
2457   MATRIX *voxelFromSRAS = MatrixInverse(sRASFromVoxel, NULL);
2458   MatrixFree(&sRASFromVoxel) ;
2459 #endif
2460 
2461   return voxelFromSRAS;
2462 }
2463 
2464 /* extract the RASToVoxel Matrix */
2465 MATRIX *GetSurfaceRASToVoxelMatrix(MRI *mri){
2466   return voxelFromSurfaceRAS_(mri);
2467 }
2468 
2469 int MRIsurfaceRASToVoxel(MRI *mri, Real xr, Real yr, Real zr,
2470                          Real *xv, Real *yv, Real *zv)
2471 {
2472   MATRIX *voxelFromSRAS;
2473   static VECTOR *sr = NULL, *vv = NULL;
2474 
2475   voxelFromSRAS=voxelFromSurfaceRAS_(mri);
2476   if (sr == NULL)
2477     sr = VectorAlloc(4, MATRIX_REAL);
2478   V4_LOAD(sr, xr, yr, zr, 1.);
2479   vv = MatrixMultiply(voxelFromSRAS, sr, vv);
2480   *xv = V3_X(vv);
2481   *yv = V3_Y(vv);
2482   *zv = V3_Z(vv);
2483 
2484   MatrixFree(&voxelFromSRAS);
2485   //  VectorFree(&sr);
2486   //  VectorFree(&vv);
2487 
2488   return (NO_ERROR);
2489 }
2490 
2491 /*------------------------------------------------------*/
2492 int
2493 MRIworldToVoxel(MRI *mri, Real xw, Real yw, Real zw,
2494                 Real *pxv, Real *pyv, Real *pzv)
2495 {
2496   VECTOR *vv, *vw;
2497   MATRIX *IfromR;
2498 
2499   // if transform is not cached yet, then
2500   if (!mri->r_to_i__)
2501     mri->r_to_i__ = extract_r_to_i(mri);
2502   if (!mri->i_to_r__)
2503     mri->i_to_r__ = extract_i_to_r(mri);
2504 
2505   IfromR = mri->r_to_i__;
2506   vw = VectorAlloc(4, MATRIX_REAL) ;
2507   V4_LOAD(vw, xw, yw, zw, 1.) ;
2508   vv = MatrixMultiply(IfromR, vw, NULL) ;
2509   *pxv = V3_X(vv);
2510   *pyv = V3_Y(vv);
2511   *pzv = V3_Z(vv);
2512 
2513   VectorFree(&vv);
2514   VectorFree(&vw);
2515 
2516   return(NO_ERROR) ;
2517 }
2518 /*-----------------------------------------------------
2519   ------------------------------------------------------*/
2520 int
2521 MRIinitHeader(MRI *mri)
2522 {
2523   mri->ptype = 2 ;
2524 
2525   /* most of these are in mm */
2526   mri->imnr0 = 1 ;
2527   mri->imnr1 = mri->depth ;
2528   mri->fov = mri->width ;
2529   mri->thick = 1.0 ;
2530   mri->xsize = 1.0 ;
2531   mri->ysize = 1.0 ;
2532   mri->zsize = 1.0 ;
2533   mri->ps = 1 ;
2534   mri->xstart = -mri->width/2.0 ;
2535   mri->xend = mri->width/2.0 ;
2536   mri->ystart = -mri->height/2.0 ;
2537   mri->yend = mri->height/2.0 ;
2538   mri->zstart = -mri->depth/2.0 ;
2539   mri->zend = mri->depth/2 ;
2540   // coronal
2541   mri->x_r = -1;
2542   mri->x_a = 0.;
2543   mri->x_s = 0.;
2544   //
2545   mri->y_r = 0.;
2546   mri->y_a = 0.;
2547   mri->y_s = -1;
2548   //
2549   mri->z_r = 0.;
2550   mri->z_a = 1;
2551   mri->z_s = 0.;
2552   //
2553   mri->c_r = mri->c_a = mri->c_s = 0.0;
2554 
2555   mri->ras_good_flag = 1;
2556   mri->gdf_image_stem[0] = '\0';
2557   mri->tag_data = NULL;
2558   mri->tag_data_size = 0;
2559 
2560   if (!mri->i_to_r__)
2561     mri->i_to_r__ = extract_i_to_r(mri);
2562   if (!mri->r_to_i__)
2563     mri->r_to_i__ = extract_r_to_i(mri);
2564 
2565   return(NO_ERROR) ;
2566 }
2567 
2568 /**
2569  * MRIreInitCache
2570  *
2571  * @param mri MRI* whose header information was modified
2572  *
2573  * @return NO_ERROR
2574  */
2575 int MRIreInitCache(MRI *mri)
2576 {
2577   if (mri->i_to_r__)
2578     {
2579       MatrixFree(&mri->i_to_r__);
2580       mri->i_to_r__ = 0;
2581     }
2582   if (mri->r_to_i__)
2583     {
2584       MatrixFree(&mri->r_to_i__);
2585       mri->r_to_i__ = 0;
2586     }
2587   mri->i_to_r__ = extract_i_to_r(mri);
2588   mri->r_to_i__ = extract_r_to_i(mri);
2589 
2590   return (NO_ERROR);
2591 }
2592 
2593 /*-----------------------------------------------------
2594   Parameters:
2595 
2596   Returns value:
2597 
2598   Description
2599   change the direction of slices
2600   ------------------------------------------------------*/
2601 MRI *
2602 MRIextract(MRI *mri_src, MRI *mri_dst, int x0, int y0, int z0,
2603            int dx, int dy, int dz)
2604 {
2605   return(MRIextractInto(mri_src, mri_dst, x0, y0, z0, dx, dy, dz, 0, 0, 0)) ;
2606 }
2607 /*-----------------------------------------------------
2608   Parameters:
2609 
2610   Returns value:
2611 
2612   Description
2613   Extract a cubic region of an MR image and return it to the caller
2614   ------------------------------------------------------*/
2615 MRI *
2616 MRIextractRegion(MRI *mri_src, MRI *mri_dst, MRI_REGION *region)
2617 {
2618   return(MRIextractInto(mri_src, mri_dst, region->x, region->y, region->z,
2619                         region->dx, region->dy, region->dz, 0, 0, 0)) ;
2620 }
2621 /*-----------------------------------------------------
2622   Parameters:
2623 
2624   Returns value:
2625 
2626   Description
2627   Extract a cubic region of an MR image and return it to the caller
2628   ------------------------------------------------------*/
2629 MRI *
2630 MRIextractIntoRegion(MRI *mri_src, MRI *mri_dst, int x0, int y0, int z0,
2631                      MRI_REGION *region)
2632 {
2633   return(MRIextractInto(mri_src, mri_dst, x0, y0, z0, region->dx, region->dy,
2634                         region->dz, region->x, region->y, region->z)) ;
2635 }
2636 /*-----------------------------------------------------
2637   Parameters:
2638 
2639   Returns value:
2640 
2641   Description
2642   Extract a cubic region of an MR image and return it to the caller
2643   ------------------------------------------------------*/
2644 MRI *
2645 MRIextractInto(MRI *mri_src, MRI *mri_dst, int x0, int y0, int z0,
2646                int dx, int dy, int dz, int x1, int y1, int z1)
2647 {
2648   int  width, height, depth, ys, zs, yd, zd, bytes, frame, xsize,ysize,zsize,
2649     dst_alloced = 0 ;
2650   Real c_r, c_a, c_s;
2651 
2652   width = mri_src->width ;
2653   depth = mri_src->depth ;
2654   height = mri_src->height ;
2655 
2656   if (z0 >= depth || y0 >= height || x0 >= width)
2657     ErrorReturn(NULL,
2658                 (ERROR_BADPARM,
2659                  "MRIextractInto: bad src location (%d, %d, %d)", x0,y0,z0));
2660   // validation
2661   if (x0 < 0)
2662     x0 = 0 ;
2663   if (y0 < 0)
2664     y0 = 0 ;
2665   if (z0 < 0)
2666     z0 = 0 ;
2667   if (x0+dx > width)
2668     dx = (width - x0) ;
2669   if (y0+dy > height)
2670     dy = (height - y0) ;
2671   if (z0+dz > depth)
2672     dz = (depth - z0) ;
2673   if (x1 < 0)
2674     x1 = 0 ;
2675   if (y1 < 0)
2676     y1 = 0 ;
2677   if (z1 < 0)
2678     z1 = 0 ;
2679 
2680   if (!mri_dst)
2681     {
2682       mri_dst = MRIallocSequence(dx, dy, dz, mri_src->type, mri_src->nframes) ;
2683       MRIcopyHeader(mri_src, mri_dst) ;
2684       mri_dst->imnr0 = z0 + mri_src->imnr0 - z1 ;
2685       mri_dst->imnr1 = mri_dst->imnr0 + dz - 1 ;
2686       dst_alloced = 1 ;
2687     }
2688 
2689   if (mri_src->type != mri_dst->type)
2690     {
2691       MRIfree(&mri_dst) ;
2692       ErrorReturn(NULL,
2693                   (ERROR_BADPARM,
2694                    "MRIextractInto: src and dst types must match"));
2695     }
2696 
2697   if (x1+dx > mri_dst->width)
2698     dx = (mri_dst->width - x1) ;
2699   if (y1+dy > mri_dst->height)
2700     dy = (mri_dst->height - y1) ;
2701   if (z1+dz > mri_dst->depth)
2702     dz = (mri_dst->depth - z1) ;
2703 
2704   xsize = mri_src->xsize ;
2705   ysize = mri_src->ysize ;
2706   zsize = mri_src->zsize ;
2707 
2708   if (dst_alloced)
2709     {
2710       mri_dst->xstart += x0*xsize ;
2711       mri_dst->xend = mri_dst->xstart + dx*xsize ;
2712       mri_dst->ystart += y0*ysize ;
2713       mri_dst->yend = mri_dst->ystart + dy*ysize ;
2714       mri_dst->zstart += z0*zsize ;
2715       mri_dst->zend = mri_dst->zstart + dz*zsize  ;
2716     }
2717 
2718   bytes = dx ;
2719   switch (mri_src->type)
2720     {
2721     case MRI_FLOAT:
2722       bytes *= sizeof(float) ;
2723       break ;
2724     case MRI_LONG:
2725       bytes *= sizeof(long) ;
2726       break ;
2727     case MRI_INT:
2728       bytes *= sizeof(int) ;
2729       break ;
2730     case MRI_SHORT:
2731       bytes *= sizeof(short) ;
2732       break ;
2733     default:
2734       break ;
2735     }
2736 
2737   for (frame = 0 ; frame < mri_src->nframes ; frame++)
2738     {
2739       for (zd = z1, zs = z0 ; zs < z0+dz ; zs++, zd++)
2740         {
2741           for (yd = y1, ys = y0 ; ys < y0+dy ; ys++, yd++)
2742             {
2743               switch (mri_src->type)
2744                 {
2745                 case MRI_UCHAR:
2746                   memcpy(&MRIseq_vox(mri_dst, x1, yd, zd,frame),
2747                          &MRIseq_vox(mri_src,x0,ys,zs,frame), bytes);
2748                   break ;
2749                 case MRI_FLOAT:
2750                   memcpy(&MRIFseq_vox(mri_dst, x1, yd, zd,frame),
2751                          &MRIFseq_vox(mri_src,x0,ys,zs,frame), bytes);
2752                   break ;
2753                 case MRI_SHORT:
2754                   memcpy(&MRISseq_vox(mri_dst, x1, yd, zd,frame),
2755                          &MRISseq_vox(mri_src,x0,ys,zs,frame), bytes);
2756                   break ;
2757                 case MRI_LONG:
2758                   memcpy(&MRILseq_vox(mri_dst, x1, yd, zd,frame),
2759                          &MRILseq_vox(mri_src,x0,ys,zs,frame), bytes);
2760                   break ;
2761                 }
2762             }
2763         }
2764     }
2765   // calculate c_ras
2766   MRIcalcCRASforExtractedVolume
2767     (mri_src, mri_dst, x0, y0, z0, x1, y1, z1, &c_r, &c_a, &c_s);
2768   mri_dst->c_r = c_r;
2769   mri_dst->c_a = c_a;
2770   mri_dst->c_s = c_s;
2771   // initialize cached transform
2772   MRIreInitCache(mri_dst);
2773 
2774   return(mri_dst) ;
2775 }
2776 /*-----------------------------------------------------
2777   Parameters:
2778 
2779   Returns value:
2780 
2781   Description
2782   change the direction of slices
2783   ------------------------------------------------------*/
2784 MRI *
2785 MRIreslice(MRI *mri_src, MRI *mri_dst, int slice_direction)
2786 {
2787   int     width, height, depth, x1, x2, x3 ;
2788   BUFTYPE *psrc, val, *pdst ;
2789 
2790   int src_slice_direction = getSliceDirection(mri_src);
2791   if (slice_direction == src_slice_direction)
2792     {
2793       mri_dst = MRIcopy(mri_src, NULL) ;
2794       return(mri_dst) ;
2795     }
2796 
2797   width = mri_src->width ;
2798   height = mri_src->height ;
2799   depth = mri_src->depth ;
2800 
2801 
2802   if ((src_slice_direction == MRI_SAGITTAL &&
2803        slice_direction == MRI_CORONAL) ||
2804       (src_slice_direction == MRI_CORONAL &&
2805        slice_direction == MRI_SAGITTAL))
2806     {
2807       /*
2808         coronal images are back to front of the head, thus the depth axis
2809         points from the nose to the back of the head, with x from neck to
2810         crown, and y from ear to ear.
2811       */
2812       /* x1 --> x3
2813          x2 --> x2
2814          x3 --> x1
2815       */
2816       if (!mri_dst)
2817         {
2818           mri_dst = MRIalloc(depth, height, width, mri_src->type) ;
2819           MRIcopyHeader(mri_src, mri_dst) ;
2820         }
2821       else if (depth != mri_dst->width || height != mri_dst->height ||
2822                width != mri_dst->depth)
2823         {
2824           ErrorReturn(NULL,
2825                       (ERROR_BADPARM,
2826                        "MRIreslice: invalid destination size (%d, %d, %d)",
2827                        mri_dst->width, mri_dst->height, mri_dst->depth)) ;
2828         }
2829 
2830       for (x3 = 0 ; x3 < depth ; x3++)
2831         {
2832           for (x2 = 0 ; x2 < height ; x2++)
2833             {
2834               psrc = &MRIvox(mri_src, 0, x2, x3) ;
2835               for (x1 = 0 ; x1 < width ; x1++)
2836                 {
2837                   /* swap so in place transformations are possible */
2838                   mri_dst->slices[x1][x2][x3] = *psrc++ ;
2839                 }
2840             }
2841         }
2842     }
2843   else
2844     if ((src_slice_direction == MRI_HORIZONTAL &&
2845          slice_direction == MRI_CORONAL) ||
2846         (src_slice_direction == MRI_CORONAL &&
2847          slice_direction == MRI_HORIZONTAL))
2848       {
2849         /*
2850           horizontal images are top to bottom of the head, thus the depth axis
2851           points from the top of the head to the neck, with x from ear to ear
2852           and y from nose to back of head.
2853         */
2854         /* x3 --> x2
2855            x2 --> x3
2856            x1 --> x1
2857         */
2858         if (!mri_dst)
2859           {
2860             mri_dst = MRIalloc(width, depth, height, mri_src->type) ;
2861             MRIcopyHeader(mri_src, mri_dst) ;
2862           }
2863         else if (depth != mri_dst->height || height != mri_dst->depth ||
2864                  width != mri_dst->width)
2865           ErrorReturn(NULL,
2866                       (ERROR_BADPARM,
2867                        "MRIreslice: invalid destination size (%d, %d, %d)",
2868                        mri_dst->width, mri_dst->height, mri_dst->depth)) ;
2869 
2870         for (x3 = 0 ; x3 < depth ; x3++)
2871           {
2872             for (x2 = 0 ; x2 < height ; x2++)
2873               {
2874                 psrc = &MRIvox(mri_src, 0, x2, x3) ;
2875                 pdst = &MRIvox(mri_dst, 0, x3, x2) ;
2876                 for (x1 = 0 ; x1 < width ; x1++)
2877                   {
2878                     /* swap so in place transformations are possible */
2879                     *pdst++ = *psrc++ ;
2880                   }
2881               }
2882           }
2883       }
2884     else
2885       if ((src_slice_direction == MRI_SAGITTAL &&
2886            slice_direction == MRI_HORIZONTAL))
2887         {
2888           /*
2889             horizontal images are top to bottom of the head,
2890             thus the depth axis
2891             points from the top of the head to the neck, with x from
2892             ear to ear
2893             and y from nose to back of head.
2894           */
2895           /* x3 --> x2
2896              x1 --> x3
2897              x2 --> x1
2898           */
2899           if (!mri_dst)
2900             {
2901               mri_dst = MRIalloc(width, depth, height, mri_src->type) ;
2902               MRIcopyHeader(mri_src, mri_dst) ;
2903             }
2904           else if (depth != mri_dst->height || height != mri_dst->depth ||
2905                    width != mri_dst->width)
2906             ErrorReturn(NULL,
2907                         (ERROR_BADPARM,
2908                          "MRIreslice: invalid destination size (%d, %d, %d)",
2909                          mri_dst->width, mri_dst->height, mri_dst->depth)) ;
2910 
2911           for (x3 = 0 ; x3 < depth ; x3++)
2912             {
2913               for (x2 = 0 ; x2 < height ; x2++)
2914                 {
2915                   psrc = &MRIvox(mri_src, 0, x2, x3) ;
2916                   for (x1 = 0 ; x1 < width ; x1++)
2917                     {
2918                       /* swap so in place transformations are possible */
2919                       mri_dst->slices[x2][x1][x3] = *psrc++ ;
2920                     }
2921                 }
2922             }
2923         }
2924       else
2925         if (src_slice_direction == MRI_HORIZONTAL &&
2926             slice_direction == MRI_SAGITTAL)
2927           {
2928             /*
2929               horizontal images are top to bottom of the head,
2930               thus the depth axis
2931               points from the top of the head to the neck,
2932               with x from ear to ear
2933               and y from nose to back of head.
2934             */
2935             /* x2 --> x3
2936                x3 --> x1
2937                x1 --> x2
2938             */
2939             if (!mri_dst)
2940               {
2941                 mri_dst = MRIalloc(width, depth, height, mri_src->type) ;
2942                 MRIcopyHeader(mri_src, mri_dst) ;
2943               }
2944             else if (depth != mri_dst->height || height != mri_dst->depth ||
2945                      width != mri_dst->width)
2946               ErrorReturn(NULL,
2947                           (ERROR_BADPARM,
2948                            "MRIreslice: invalid destination size (%d, %d, %d)",
2949                            mri_dst->width, mri_dst->height, mri_dst->depth)) ;
2950 
2951             for (x3 = 0 ; x3 < depth ; x3++)
2952               {
2953                 for (x2 = 0 ; x2 < height ; x2++)
2954                   {
2955                     psrc = &MRIvox(mri_src, 0, x2, x3) ;
2956                     for (x1 = 0 ; x1 < width ; x1++)
2957                       {
2958                         /* swap so in place transformations are possible */
2959                         mri_dst->slices[x1][x3][x2] = *psrc++ ;
2960                       }
2961                   }
2962               }
2963           }
2964         else
2965           switch (src_slice_direction)
2966             {
2967             default:
2968               MRIfree(&mri_dst) ;
2969               ErrorReturn(NULL,
2970                           (ERROR_BADPARM,
2971                            "MRIreslice: mri_src unknown slice direction %d",
2972                            src_slice_direction)) ;
2973               break ;
2974             case MRI_CORONAL:
2975               /*
2976                 coronal images are back to front of the head,
2977                 thus the depth axis
2978                 points from the nose to the back of the head,
2979                 with x from neck to
2980                 crown, and y from ear to ear.
2981               */
2982               switch (slice_direction)
2983                 {
2984                 case MRI_SAGITTAL:
2985                   /* x1 --> x3
2986                      x2 --> x2
2987                      x3 --> x1
2988                   */
2989                   if (!mri_dst)
2990                     {
2991                       mri_dst = MRIalloc(depth, height, width, mri_src->type) ;
2992                       MRIcopyHeader(mri_src, mri_dst) ;
2993                     }
2994                   else if (depth != mri_dst->width ||
2995                            height != mri_dst->height ||
2996                            width != mri_dst->depth)
2997                     ErrorReturn
2998                       (NULL,
2999                        (ERROR_BADPARM,
3000                         "MRIreslice: invalid destination size (%d, %d, %d)",
3001                         mri_dst->width, mri_dst->height, mri_dst->depth)) ;
3002 
3003                   for (x3 = 0 ; x3 < depth ; x3++)
3004                     {
3005                       for (x2 = 0 ; x2 < height ; x2++)
3006                         {
3007                           psrc = &MRIvox(mri_src, 0, x2, x3) ;
3008                           for (x1 = 0 ; x1 < width ; x1++)
3009                             {
3010                               /* swap so in place transformations
3011                                  are possible */
3012                               val = *psrc++ ;
3013 #if 0
3014                               mri_dst->slices[x3][x2][x1] =
3015                                 mri_src->slices[x1][x2][x3] ;
3016 #endif
3017                               mri_dst->slices[x1][x2][x3] = val ;
3018                             }
3019                         }
3020                     }
3021                   break ;
3022                 case MRI_HORIZONTAL:
3023                   break ;
3024                 }
3025               break ;
3026             case MRI_SAGITTAL:
3027               /*
3028                 sagittal images are slices in
3029                 the plane of the nose, with depth going
3030                 from ear to ear.
3031               */
3032               break ;
3033             }
3034   setDirectionCosine(mri_dst, slice_direction);
3035   mri_dst->ras_good_flag = 0;
3036   return(mri_dst) ;
3037 }
3038 /*-----------------------------------------------------
3039   Parameters:
3040 
3041   Returns value:
3042 
3043   Description
3044   Set an MRI intensity values to 0
3045   ------------------------------------------------------*/
3046 int
3047 MRIclear(MRI *mri)
3048 {
3049   int   width, depth, height, bytes, y, z, frame, nframes ;
3050 
3051   width = mri->width ;
3052   height = mri->height ;
3053   depth = mri->depth ;
3054   nframes = mri->nframes ;
3055   bytes = width ;
3056 
3057   switch (mri->type)
3058     {
3059     case MRI_UCHAR:
3060       bytes *= sizeof(unsigned char) ;
3061       break ;
3062     case MRI_BITMAP:
3063       bytes /= 8 ;
3064       break ;
3065     case MRI_FLOAT:
3066       bytes *= sizeof(float) ;
3067       break ;
3068     case MRI_LONG:
3069       bytes *= sizeof(long) ;
3070       break ;
3071     case MRI_INT:
3072       bytes *= sizeof(int) ;
3073       break ;
3074     case MRI_SHORT:
3075       bytes *= sizeof(short) ;
3076       break ;
3077     default:
3078       ErrorReturn(ERROR_UNSUPPORTED,
3079                   (ERROR_UNSUPPORTED,
3080                    "MRIclear: unsupported input type %d", mri->type)) ;
3081       break ;
3082     }
3083 
3084   for (frame = 0 ; frame < nframes ; frame++)
3085     {
3086       for (z = 0 ; z < depth ; z++)
3087         {
3088           for (y = 0 ; y < height ; y++)
3089             memset(mri->slices[z+frame*depth][y], 0, bytes) ;
3090         }
3091     }
3092 
3093   return(NO_ERROR) ;
3094 }
3095 /*-----------------------------------------------------
3096   Parameters:
3097 
3098   Returns value:
3099 
3100   Description
3101   find the principle components of a (binary) MRI. The
3102   eigenvectors are the columns of the matrix mEvectors, the
3103   eigenvalues are returned in the array evalues and the means
3104   in means (these last two must be three elements long.)
3105   ------------------------------------------------------*/
3106 int
3107 MRIcenterOfMass(MRI *mri,double *means, BUFTYPE threshold)
3108 {
3109   int     width, height, depth, x, y, z ;
3110   long    npoints ;
3111   double  mx, my, mz, weight ;
3112   Real    val ;
3113 
3114   width = mri->width ;
3115   height = mri->height ;
3116   depth = mri->depth ;
3117 
3118   mx = my = mz = weight = 0.0f ; npoints = 0L ;
3119 
3120   for (z = 0 ; z < depth ; z++)
3121     {
3122       for (y = 0 ; y < height ; y++)
3123         {
3124           for (x = 0 ; x < width ; x++)
3125             {
3126               MRIsampleVolumeType(mri, x,  y, z, &val, SAMPLE_NEAREST) ;
3127               if (val > threshold)
3128                 {
3129                   weight += val ;
3130                   mx += (float)x*val ;
3131                   my += (float)y*val ;
3132                   mz += (float)z*val ;
3133                   npoints++ ;
3134                 }
3135             }
3136         }
3137     }
3138 
3139   if (weight > 0.0)
3140     {
3141       mx /= weight ;
3142       my /= weight  ;
3143       mz /= weight ;
3144       means[0] = mx ;
3145       means[1] = my ;
3146       means[2] = mz ;
3147     }
3148   else
3149     means[0] = means[1] = means[2] = 0.0f ;
3150 
3151 
3152   return(NO_ERROR) ;
3153 }
3154 /*-----------------------------------------------------
3155   Parameters:
3156 
3157   Returns value:
3158 
3159   Description
3160   find the principle components of a (binary) MRI. The
3161   eigenvectors are the columns of the matrix mEvectors, the
3162   eigenvalues are returned in the array evalues and the means
3163   in means (these last two must be three elements long.)
3164   ------------------------------------------------------*/
3165 int
3166 MRIprincipleComponents(MRI *mri, MATRIX *mEvectors, float *evalues,
3167                        double *means, BUFTYPE threshold)
3168 {
3169   int     width, height, depth, x, y, z ;
3170   BUFTYPE *psrc, val ;
3171   long    npoints ;
3172   MATRIX  *mCov, *mX, *mXT, *mTmp ;
3173   double  mx, my, mz, weight ;
3174 
3175   if (mri->type != MRI_UCHAR)
3176     ErrorReturn(ERROR_UNSUPPORTED,
3177                 (ERROR_UNSUPPORTED,
3178                  "MRIprincipleComponents: unsupported input type %d",
3179                  mri->type)) ;
3180 
3181   width = mri->width ;
3182   height = mri->height ;
3183   depth = mri->depth ;
3184 
3185   mx = my = mz = weight = 0.0f ; npoints = 0L ;
3186 
3187   for (z = 0 ; z < depth ; z++)
3188     {
3189       for (y = 0 ; y < height ; y++)
3190         {
3191           psrc = &MRIvox(mri, 0, y, z) ;
3192           for (x = 0 ; x < width ; x++)
3193             {
3194               val = *psrc++ ;
3195               if (val > threshold)
3196                 {
3197                   weight += val ;
3198                   mx += (float)x*val ;
3199                   my += (float)y*val ;
3200                   mz += (float)z*val ;
3201                   npoints++ ;
3202                 }
3203             }
3204         }
3205     }
3206 
3207   if (weight > 0.0)
3208     {
3209       mx /= weight ;
3210       my /= weight  ;
3211       mz /= weight ;
3212       means[0] = mx ;
3213       means[1] = my ;
3214       means[2] = mz ;
3215     }
3216   else
3217     means[0] = means[1] = means[2] = 0.0f ;
3218 
3219   mX = MatrixAlloc(3, 1, MATRIX_REAL) ;     /* zero-mean coordinate vector */
3220   mXT = NULL ;                              /* transpose of above */
3221   mTmp = MatrixAlloc(3, 3, MATRIX_REAL) ;   /* tmp matrix for covariance */
3222   mCov = MatrixAlloc(3, 3, MATRIX_REAL) ;   /* covariance matrix */
3223 
3224   for (z = 0 ; z < depth ; z++)
3225     {
3226       for (y = 0 ; y < height ; y++)
3227         {
3228           psrc = &MRIvox(mri, 0, y, z) ;
3229           for (x = 0 ; x < width ; x++)
3230             {
3231               val = *psrc++ ;
3232               if (val > threshold)
3233                 {
3234                   mX->rptr[1][1] = (x - (int)mx)*val ;
3235                   mX->rptr[2][1] = (y - (int)my)*val ;
3236                   mX->rptr[3][1] = (z - (int)mz)*val ;
3237                   mXT = MatrixTranspose(mX, mXT) ;
3238                   mTmp = MatrixMultiply(mX, mXT, mTmp) ;
3239                   mCov = MatrixAdd(mTmp, mCov, mCov) ;
3240                 }
3241             }
3242         }
3243     }
3244 
3245   if (weight > 0)
3246     MatrixScalarMul(mCov, 1.0f/weight, mCov) ;
3247 
3248   MatrixEigenSystem(mCov, evalues, mEvectors) ;
3249 
3250   return(NO_ERROR) ;
3251 }
3252 /*-----------------------------------------------------
3253   Parameters:
3254 
3255   Returns value:
3256 
3257   Description
3258   find the principle components of a (binary) MRI. The
3259   eigenvectors are the columns of the matrix mEvectors, the
3260   eigenvalues are returned in the array evalues and the means
3261   in means (these last two must be three elements long.)
3262   ------------------------------------------------------*/
3263 int
3264 MRIbinaryPrincipleComponents(MRI *mri, MATRIX *mEvectors, float *evalues,
3265                              double *means, BUFTYPE threshold)
3266 {
3267   int     width, height, depth, x, y, z ;
3268   BUFTYPE *psrc, val ;
3269   long    npoints ;
3270   MATRIX  *mCov, *mX, *mXT, *mTmp ;
3271   double  mx, my, mz, weight ;
3272 
3273   if (mri->type != MRI_UCHAR)
3274     ErrorReturn(ERROR_UNSUPPORTED,
3275                 (ERROR_UNSUPPORTED,
3276                  "MRIprincipleComponents: unsupported input type %d",
3277                  mri->type)) ;
3278 
3279   width = mri->width ;
3280   height = mri->height ;
3281   depth = mri->depth ;
3282 
3283   mx = my = mz = weight = 0.0f ; npoints = 0L ;
3284 
3285   for (z = 0 ; z < depth ; z++)
3286     {
3287       for (y = 0 ; y < height ; y++)
3288         {
3289           psrc = &MRIvox(mri, 0, y, z) ;
3290           for (x = 0 ; x < width ; x++)
3291             {
3292               val = *psrc++ ;
3293               if (val > threshold)
3294                 {
3295                   weight++ ;
3296                   mx += (float)x ;
3297                   my += (float)y ;
3298                   mz += (float)z ;
3299                   npoints++ ;
3300                 }
3301             }
3302         }
3303     }
3304 
3305   if (weight > 0.0)
3306     {
3307       mx /= weight ;
3308       my /= weight  ;
3309       mz /= weight ;
3310       means[0] = mx ;
3311       means[1] = my ;
3312       means[2] = mz ;
3313     }
3314   else
3315     means[0] = means[1] = means[2] = 0.0f ;
3316 
3317   mX = MatrixAlloc(3, 1, MATRIX_REAL) ;     /* zero-mean coordinate vector */
3318   mXT = NULL ;                              /* transpose of above */
3319   mTmp = MatrixAlloc(3, 3, MATRIX_REAL) ;   /* tmp matrix for covariance */
3320   mCov = MatrixAlloc(3, 3, MATRIX_REAL) ;   /* covariance matrix */
3321 
3322   for (z = 0 ; z < depth ; z++)
3323     {
3324       for (y = 0 ; y < height ; y++)
3325         {
3326           psrc = &MRIvox(mri, 0, y, z) ;
3327           for (x = 0 ; x < width ; x++)
3328             {
3329               val = *psrc++ ;
3330               if (val > threshold)
3331                 {
3332                   mX->rptr[1][1] = (x - (int)mx) ;
3333                   mX->rptr[2][1] = (y - (int)my) ;
3334                   mX->rptr[3][1] = (z - (int)mz) ;
3335                   mXT = MatrixTranspose(mX, mXT) ;
3336                   mTmp = MatrixMultiply(mX, mXT, mTmp) ;
3337                   mCov = MatrixAdd(mTmp, mCov, mCov) ;
3338                 }
3339             }
3340         }
3341     }
3342 
3343   if (weight > 0)
3344     MatrixScalarMul(mCov, 1.0f/weight, mCov) ;
3345 
3346   MatrixEigenSystem(mCov, evalues, mEvectors) ;
3347 
3348   return(NO_ERROR) ;
3349 }
3350 /*-----------------------------------------------------
3351   Parameters:
3352 
3353   Returns value:
3354 
3355   Description
3356   threshold an MRI.
3357   ------------------------------------------------------*/
3358 MRI *
3359 MRIthresholdRangeInto(MRI *mri_src,MRI *mri_dst,BUFTYPE low_val,BUFTYPE hi_val)
3360 {
3361   int     width, height, depth, x, y, z ;
3362   BUFTYPE *psrc, *pdst, val ;
3363   float   *pfsrc, *pfdst, fval ;
3364 
3365   if (!mri_dst)
3366     mri_dst = MRIclone(mri_src, NULL) ;
3367 
3368   width = mri_src->width ;
3369   height = mri_src->height ;
3370   depth = mri_src->depth ;
3371 
3372   switch (mri_src->type)
3373     {
3374     case MRI_UCHAR:
3375       for (z = 0 ; z < depth ; z++)
3376         {
3377           for (y = 0 ; y < height ; y++)
3378             {
3379               psrc = &MRIvox(mri_src, 0, y, z) ;
3380               pdst = &MRIvox(mri_dst, 0, y, z) ;
3381               for (x = 0 ; x < width ; x++, pdst++)
3382                 {
3383                   val = *psrc++ ;
3384                   if (val >=  low_val && val <= hi_val)
3385                     *pdst = val ;
3386                   else
3387                     *pdst = 0 ;
3388                 }
3389             }
3390         }
3391       break ;
3392     case MRI_FLOAT:
3393       for (z = 0 ; z < depth ; z++)
3394         {
3395           for (y = 0 ; y < height ; y++)
3396             {
3397               pfsrc = &MRIFvox(mri_src, 0, y, z) ;
3398               pfdst = &MRIFvox(mri_dst, 0, y, z) ;
3399               for (x = 0 ; x < width ; x++, pdst++)
3400                 {
3401                   fval = *pfsrc++ ;
3402                   if (fval >=  low_val && fval <= hi_val)
3403                     *pfdst = fval ;
3404                   else
3405                     *pfdst = 0 ;
3406                 }
3407             }
3408         }
3409       break ;
3410     default:
3411       ErrorReturn(mri_dst,
3412                   (ERROR_UNSUPPORTED,
3413                    "MRIthresholdRangeInto: unsupported type %d",
3414                    mri_src->type)) ;
3415       break ;
3416     }
3417   return(mri_dst) ;
3418 }
3419 /*-----------------------------------------------------
3420   Parameters:
3421 
3422   Returns value:
3423 
3424   Description
3425   threshold an MRI.
3426   ------------------------------------------------------*/
3427 MRI *
3428 MRIthreshold(MRI *mri_src, MRI *mri_dst, float threshold)
3429 {
3430   int     width, height, depth, x, y, z ;
3431   float   val ;
3432 
3433   if (!mri_dst)
3434     mri_dst = MRIclone(mri_src, NULL) ;
3435 
3436   width = mri_src->width ;
3437   height = mri_src->height ;
3438   depth = mri_src->depth ;
3439 
3440   for (z = 0 ; z < depth ; z++)
3441     {
3442       for (y = 0 ; y < height ; y++)
3443         {
3444           for (x = 0 ; x < width ; x++)
3445             {
3446               val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
3447               if (val < threshold)
3448                 val = 0 ;
3449               MRIsetVoxVal(mri_dst, x, y, z, 0, val) ;
3450             }
3451         }
3452     }
3453 
3454   return(mri_dst) ;
3455 }
3456 /*-----------------------------------------------------
3457   Parameters:
3458 
3459   Returns value:
3460 
3461   Description
3462   threshold an MRI.
3463   ------------------------------------------------------*/
3464 MRI  *
3465 MRIinvertContrast(MRI *mri_src, MRI *mri_dst, float threshold)
3466 {
3467   int     width, height, depth, x, y, z ;
3468   BUFTYPE *psrc, *pdst, val ;
3469 
3470   if (!mri_dst)
3471     mri_dst = MRIclone(mri_src, NULL) ;
3472 
3473   width = mri_src->width ;
3474   height = mri_src->height ;
3475   depth = mri_src->depth ;
3476 
3477   for (z = 0 ; z < depth ; z++)
3478     {
3479       for (y = 0 ; y < height ; y++)
3480         {
3481           psrc = &MRIvox(mri_src, 0, y, z) ;
3482           pdst = &MRIvox(mri_dst, 0, y, z) ;
3483           for (x = 0 ; x < width ; x++)
3484             {
3485               val = *psrc++ ;
3486               if (val > threshold)
3487                 val = 255 - val ;
3488               *pdst++ = val ;
3489             }
3490         }
3491     }
3492 
3493   return(mri_dst) ;
3494 }
3495 /*-----------------------------------------------------
3496   Parameters:
3497 
3498   Returns value:
3499 
3500   Description
3501   threshold an MRI.
3502   ------------------------------------------------------*/
3503 MRI *
3504 MRIbinarize(MRI *mri_src, MRI *mri_dst, BUFTYPE threshold, BUFTYPE low_val,
3505             BUFTYPE hi_val)
3506 {
3507   int     width, height, depth, x, y, z, f ;
3508   Real    val ;
3509 
3510   if (!mri_dst)
3511     mri_dst = MRIclone(mri_src, NULL) ;
3512 
3513   width = mri_src->width ;
3514   height = mri_src->height ;
3515   depth = mri_src->depth ;
3516 
3517   for (f = 0 ; f < mri_src->nframes ; f++)
3518     {
3519       for (z = 0 ; z < depth ; z++)
3520         {
3521           for (y = 0 ; y < height ; y++)
3522             {
3523               for (x = 0 ; x < width ; x++)
3524                 {
3525                   MRIsampleVolumeFrameType
3526                     (mri_src, x, y, z, f, SAMPLE_NEAREST, &val) ;
3527                   if (val < threshold)
3528                     val = low_val ;
3529                   else
3530                     val = hi_val ;
3531                   MRIsetVoxVal(mri_dst, x, y, z, f, val) ;
3532                 }
3533             }
3534         }
3535     }
3536 
3537   return(mri_dst) ;
3538 }
3539 
3540 /*-----------------------------------------------------*/
3541 MRI *MRIsubtract(MRI *mri1, MRI *mri2, MRI *mri_dst)
3542 {
3543   int     nframes, width, height, depth, x, y, z, f, s ;
3544   float v1, v2, v=0.0;
3545   BUFTYPE *p1=NULL, *p2=NULL, *pdst=NULL ;
3546   short *ps1=NULL, *ps2=NULL, *psdst=NULL ;
3547   int   *pi1=NULL, *pi2=NULL, *pidst=NULL ;
3548   long  *pl1=NULL, *pl2=NULL, *pldst=NULL ;
3549   float *pf1=NULL, *pf2=NULL, *pfdst=NULL ;
3550 
3551   width = mri1->width ;
3552   height = mri1->height ;
3553   depth = mri1->depth ;
3554   nframes = mri1->nframes ;
3555   if(nframes == 0) nframes = 1;
3556 
3557   if (!mri_dst){
3558     mri_dst = MRIallocSequence(width, height, depth, mri1->type,nframes) ;
3559     MRIcopyHeader(mri1, mri_dst) ;
3560   }
3561 
3562   if(mri1->type != mri2->type){
3563     /* Generic but slow */
3564     for (f = 0 ; f < nframes ; f++){
3565       for (z = 0 ; z < depth ; z++){
3566         for (y = 0 ; y < height ; y++){
3567           for (x = 0 ; x < width ; x++){
3568             v1 = MRIgetVoxVal(mri1,x,y,z,f);
3569             v2 = MRIgetVoxVal(mri2,x,y,z,f);
3570             v = v1-v2;
3571             MRIsetVoxVal(mri_dst,x,y,z,f,v);
3572           }
3573         }
3574       }
3575     }
3576     return(mri_dst) ;
3577   }
3578 
3579 
3580   s = 0;
3581   for (f = 0 ; f < nframes ; f++){
3582     for (z = 0 ; z < depth ; z++){
3583       for (y = 0 ; y < height ; y++){
3584 
3585         switch(mri_dst->type){
3586         case MRI_UCHAR: pdst  =           mri_dst->slices[s][y] ; break;
3587         case MRI_SHORT: psdst = (short *) mri_dst->slices[s][y] ; break;
3588         case MRI_INT:   pidst = (int *)   mri_dst->slices[s][y] ; break;
3589         case MRI_LONG:  pldst = (long *)  mri_dst->slices[s][y] ; break;
3590         case MRI_FLOAT: pfdst = (float *) mri_dst->slices[s][y] ; break;
3591         }
3592         switch(mri1->type){
3593         case MRI_UCHAR:
3594           p1 = mri1->slices[s][y] ;
3595           p2 = mri2->slices[s][y] ;
3596           break;
3597         case MRI_SHORT:
3598           ps1 = (short *) mri1->slices[s][y] ;
3599           ps2 = (short *) mri2->slices[s][y] ;
3600           break;
3601         case MRI_INT:
3602           pi1 = (int *) mri1->slices[s][y] ;
3603           pi2 = (int *) mri2->slices[s][y] ;
3604           break;
3605         case MRI_LONG:
3606           pl1 = (long *) mri1->slices[s][y] ;
3607           pl2 = (long *) mri2->slices[s][y] ;
3608           break;
3609         case MRI_FLOAT:
3610           pf1 = (float *) mri1->slices[s][y] ;
3611           pf2 = (float *) mri2->slices[s][y] ;
3612           break;
3613         }
3614 
3615         for (x = 0 ; x < width ; x++){
3616 
3617           switch(mri1->type){
3618           case MRI_UCHAR: v = (float)(*p1++)  - (float)(*p2++);  break;
3619           case MRI_SHORT: v = (float)(*ps1++) - (float)(*ps2++); break;
3620           case MRI_INT:   v = (float)(*pi1++) - (float)(*pi2++); break;
3621           case MRI_LONG:  v = (float)(*pl1++) - (float)(*pl2++); break;
3622           case MRI_FLOAT: v = (float)(*pf1++) - (float)(*pf2++); break;
3623           }
3624 
3625           switch(mri_dst->type){
3626           case MRI_UCHAR: (*pdst++)  = (BUFTYPE) v; break;
3627           case MRI_SHORT: (*psdst++) = (short)   v; break;
3628           case MRI_INT:   (*pidst++) = (int)     v; break;
3629           case MRI_LONG:  (*pldst++) = (long)    v; break;
3630           case MRI_FLOAT: (*pfdst++) = (float)   v; break;
3631           }
3632 
3633         }
3634       }
3635       s++;
3636     }
3637   }
3638 
3639   return(mri_dst) ;
3640 }
3641 #if 0
3642 /*------------------------------------------------------
3643   MRIsubtract(mri1,mri2,mridiff) - computes mri1-mri2.
3644   ------------------------------------------------------*/
3645 MRI *MRIsubtract(MRI *mri1, MRI *mri2, MRI *mri_dst)
3646 {
3647   int     nframes, width, height, depth, x, y, z, f ;
3648   float v1, v2, vdiff;
3649 
3650   width = mri1->width ;
3651   height = mri1->height ;
3652   depth = mri1->depth ;
3653   nframes = mri1->nframes ;
3654   if(nframes == 0) nframes = 1;
3655 
3656   if (!mri_dst){
3657     mri_dst = MRIallocSequence(width, height, depth, mri1->type,nframes) ;
3658     MRIcopyHeader(mri1, mri_dst) ;
3659   }
3660 
3661   for (z = 0 ; z < depth ; z++){
3662     for (y = 0 ; y < height ; y++){
3663       for (x = 0 ; x < width ; x++){
3664         for (f = 0 ; f < nframes ; f++){
3665           v1 = MRIgetVoxVal(mri1,x,y,z,f);
3666           v2 = MRIgetVoxVal(mri2,x,y,z,f);
3667           vdiff = v1-v2;
3668           MRIsetVoxVal(mri_dst,x,y,z,f,vdiff);
3669         }
3670       }
3671     }
3672   }
3673   return(mri_dst) ;
3674 }
3675 #endif
3676 /*-----------------------------------------------------
3677   ------------------------------------------------------*/
3678 MRI *
3679 MRIabsdiff(MRI *mri1, MRI *mri2, MRI *mri_dst)
3680 {
3681   int     width, height, depth, x, y, z ;
3682   BUFTYPE *p1, *p2, *pdst, v1, v2 ;
3683   float   f1, f2 ;
3684 
3685   width = mri1->width ;
3686   height = mri1->height ;
3687   depth = mri1->depth ;
3688 
3689   if (!mri_dst)
3690     {
3691       mri_dst = MRIalloc(width, height, depth, mri1->type) ;
3692       MRIcopyHeader(mri1, mri_dst) ;
3693     }
3694 
3695   if (mri1->type == MRI_UCHAR && mri2->type == MRI_UCHAR)
3696     {
3697       for (z = 0 ; z < depth ; z++)
3698         {
3699           for (y = 0 ; y < height ; y++)
3700             {
3701               p1 = mri1->slices[z][y] ;
3702               p2 = mri2->slices[z][y] ;
3703               pdst = mri_dst->slices[z][y] ;
3704               for (x = 0 ; x < width ; x++)
3705                 {
3706                   v1 = *p1++ ;
3707                   v2 = *p2++ ;
3708                   if (v1 > v2)
3709                     *pdst++ = v1 - v2 ;
3710                   else
3711                     *pdst++ = v2 - v1 ;
3712                 }
3713             }
3714         }
3715     }
3716   else
3717     {
3718       for (z = 0 ; z < depth ; z++)
3719         {
3720           for (y = 0 ; y < height ; y++)
3721             {
3722               for (x = 0 ; x < width ; x++)
3723                 {
3724                   f1 = MRIgetVoxVal(mri1, x, y, z, 0)  ;
3725                   f2 = MRIgetVoxVal(mri2, x, y, z, 0)  ;
3726                   MRIsetVoxVal(mri_dst, x, y, z, 0, fabs(f1 - f2)) ;
3727                 }
3728             }
3729         }
3730     }
3731   return(mri_dst) ;
3732 }
3733 /*-----------------------------------------------------
3734   ------------------------------------------------------*/
3735 MRI *MRIabs(MRI *mri_src, MRI *mri_dst)
3736 {
3737   int   width, height, depth, nframes, x, y, z,f ;
3738   float val;
3739 
3740   width = mri_src->width ;
3741   height = mri_src->height ;
3742   depth = mri_src->depth ;
3743   nframes = mri_src->nframes;
3744 
3745   if (!mri_dst){
3746     mri_dst = MRIallocSequence(width, height, depth, mri_src->type, nframes) ;
3747     MRIcopyHeader(mri_src, mri_dst) ;
3748   }
3749 
3750   for (z = 0 ; z < depth ; z++){
3751     for (y = 0 ; y < height ; y++){
3752       for (x = 0 ; x < width ; x++){
3753         for (f = 0 ; f < nframes ; f++){
3754           val = fabs(MRIgetVoxVal(mri_src,x,y,z,f));
3755           MRIsetVoxVal(mri_src,x,y,z,f,val);
3756         }
3757       }
3758     }
3759   }
3760   return(mri_dst) ;
3761 }
3762 /*-----------------------------------------------------*/
3763 MRI * MRIadd(MRI *mri1, MRI *mri2, MRI *mri_dst)
3764 {
3765   int     nframes, width, height, depth, x, y, z, f, s ;
3766   float v1, v2, v=0.0;
3767   BUFTYPE *p1=NULL, *p2=NULL, *pdst=NULL ;
3768   short *ps1=NULL, *ps2=NULL, *psdst=NULL ;
3769   int   *pi1=NULL, *pi2=NULL, *pidst=NULL ;
3770   long  *pl1=NULL, *pl2=NULL, *pldst=NULL ;
3771   float *pf1=NULL, *pf2=NULL, *pfdst=NULL ;
3772 
3773   width = mri1->width ;
3774   height = mri1->height ;
3775   depth = mri1->depth ;
3776   nframes = mri1->nframes ;
3777   if(nframes == 0) nframes = 1;
3778 
3779   if (!mri_dst){
3780     mri_dst = MRIallocSequence(width, height, depth, mri1->type,nframes) ;
3781     MRIcopyHeader(mri1, mri_dst) ;
3782   }
3783 
3784   if(mri1->type == MRI_UCHAR || (mri1->type != mri2->type)){
3785     /* Generic but slow */
3786     for (f = 0 ; f < nframes ; f++){
3787       for (z = 0 ; z < depth ; z++){
3788         for (y = 0 ; y < height ; y++){
3789           for (x = 0 ; x < width ; x++){
3790             v1 = MRIgetVoxVal(mri1,x,y,z,f);
3791             v2 = MRIgetVoxVal(mri2,x,y,z,f);
3792             v = v1+v2;
3793             if (mri_dst->type == MRI_UCHAR && v > 255)
3794               v = 255 ;
3795             MRIsetVoxVal(mri_dst,x,y,z,f,v);
3796           }
3797         }
3798       }
3799     }
3800     return(mri_dst) ;
3801   }
3802 
3803 
3804   s = 0;
3805   for (f = 0 ; f < nframes ; f++){
3806     for (z = 0 ; z < depth ; z++){
3807       for (y = 0 ; y < height ; y++){
3808 
3809         switch(mri_dst->type){
3810         case MRI_UCHAR: pdst  = mri_dst->slices[s][y] ; break;
3811         case MRI_SHORT: psdst = (short *) mri_dst->slices[s][y] ; break;
3812         case MRI_INT:   pidst = (int *)   mri_dst->slices[s][y] ; break;
3813         case MRI_LONG:  pldst = (long *)  mri_dst->slices[s][y] ; break;
3814         case MRI_FLOAT: pfdst = (float *) mri_dst->slices[s][y] ; break;
3815         }
3816 
3817         switch(mri1->type){
3818         case MRI_UCHAR:
3819           p1 = mri1->slices[s][y] ;
3820           p2 = mri2->slices[s][y] ;
3821           break;
3822         case MRI_SHORT:
3823           ps1 = (short *) mri1->slices[s][y] ;
3824           ps2 = (short *) mri2->slices[s][y] ;
3825           break;
3826         case MRI_INT:
3827           pi1 = (int *) mri1->slices[s][y] ;
3828           pi2 = (int *) mri2->slices[s][y] ;
3829           break;
3830         case MRI_LONG:
3831           pl1 = (long *) mri1->slices[s][y] ;
3832           pl2 = (long *) mri2->slices[s][y] ;
3833           break;
3834         case MRI_FLOAT:
3835           pf1 = (float *) mri1->slices[s][y] ;
3836           pf2 = (float *) mri2->slices[s][y] ;
3837           break;
3838         }
3839 
3840         for (x = 0 ; x < width ; x++){
3841 
3842           switch(mri_dst->type){
3843           case MRI_UCHAR:
3844             switch(mri1->type){
3845             case MRI_UCHAR: (*pdst++) = (BUFTYPE) ((*p1++)+(*p2++));   break;
3846             case MRI_SHORT: (*pdst++) = (BUFTYPE) ((*ps1++)+(*ps2++)); break;
3847             case MRI_INT:   (*pdst++) = (BUFTYPE) ((*pi1++)+(*pi2++)); break;
3848             case MRI_LONG:  (*pdst++) = (BUFTYPE) ((*pl1++)+(*pl2++)); break;
3849             case MRI_FLOAT: (*pdst++) = (BUFTYPE) ((*pf1++)+(*pf2++)); break;
3850             }
3851             break;
3852           case MRI_SHORT:
3853             switch(mri1->type){
3854             case MRI_UCHAR: (*psdst++) = ((short)(*p1++)+(*p2++));   break;
3855             case MRI_SHORT: (*psdst++) = (short) ((*ps1++)+(*ps2++)); break;
3856             case MRI_INT:   (*psdst++) = (short) ((*pi1++)+(*pi2++)); break;
3857             case MRI_LONG:  (*psdst++) = (short) ((*pl1++)+(*pl2++)); break;
3858             case MRI_FLOAT: (*psdst++) = (short) ((*pf1++)+(*pf2++)); break;
3859             }
3860             break;
3861           case MRI_INT:
3862             switch(mri1->type){
3863             case MRI_UCHAR: (*pidst++) = ((int)(*p1++)+(*p2++));   break;
3864             case MRI_SHORT: (*pidst++) = ((int)(*ps1++)+(*ps2++)); break;
3865             case MRI_INT:   (*pidst++) = (int) ((*pi1++)+(*pi2++)); break;
3866             case MRI_LONG:  (*pidst++) = (int) ((*pl1++)+(*pl2++)); break;
3867             case MRI_FLOAT: (*pidst++) = (int) ((*pf1++)+(*pf2++)); break;
3868             }
3869             break;
3870           case MRI_LONG:
3871             switch(mri1->type){
3872             case MRI_UCHAR: (*pldst++) = ((long)(*p1++)+(*p2++));   break;
3873             case MRI_SHORT: (*pldst++) = ((long)(*ps1++)+(*ps2++)); break;
3874             case MRI_INT:   (*pldst++) = ((long)(*pi1++)+(*pi2++)); break;
3875             case MRI_LONG:  (*pldst++) = (long) ((*pl1++)+(*pl2++)); break;
3876             case MRI_FLOAT: (*pldst++) = (long) ((*pf1++)+(*pf2++)); break;
3877             }
3878             break;
3879           case MRI_FLOAT:
3880             switch(mri1->type){
3881             case MRI_UCHAR: (*pfdst++) = ((float)(*p1++)+(*p2++)); break;
3882             case MRI_SHORT: (*pfdst++) = ((float)(*ps1++)+(*ps2++)); break;
3883             case MRI_INT:   (*pfdst++) = ((float)(*pi1++)+(*pi2++)); break;
3884             case MRI_LONG:  (*pfdst++) = ((float)(*pl1++)+(*pl2++)); break;
3885             case MRI_FLOAT: (*pfdst++) =         (*pf1++)+(*pf2++);  break;
3886             }
3887             break;
3888           }
3889         }
3890       }
3891       s++;
3892     }
3893   }
3894 
3895   return(mri_dst) ;
3896 }
3897 /*-----------------------------------------------------------
3898   MRIaverage() - computes average of source and destination.
3899   ------------------------------------------------------*/
3900 MRI *
3901 MRIaverage(MRI *mri_src, int dof, MRI *mri_dst)
3902 {
3903   int     width, height, depth, x, y, z, f ;
3904   Real    src, dst ;
3905 
3906   width = mri_src->width ;
3907   height = mri_src->height ;
3908   depth = mri_src->depth ;
3909 
3910   if (!mri_dst)
3911     {
3912       mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
3913       MRIcopyHeader(mri_src, mri_dst) ;
3914     }
3915 
3916   if (!MRIcheckSize(mri_src, mri_dst,0,0,0))
3917     ErrorReturn(NULL,
3918                 (ERROR_BADPARM,"MRIaverage: incompatible volume dimensions"));
3919 #if 0
3920   if ((mri_src->type != MRI_UCHAR) || (mri_dst->type != MRI_UCHAR))
3921     ErrorReturn(NULL,
3922                 (ERROR_UNSUPPORTED,
3923                  "MRISaverage: unsupported voxel format %d",mri_src->type));
3924 #endif
3925 
3926   for (f = 0 ; f < mri_src->nframes ; f++)
3927     {
3928       for (z = 0 ; z < depth ; z++)
3929         {
3930           for (y = 0 ; y < height ; y++)
3931             {
3932               for (x = 0 ; x < width ; x++)
3933                 {
3934                   MRIsampleVolumeFrameType
3935                     (mri_src, x,  y, z, f, SAMPLE_NEAREST, &src) ;
3936                   MRIsampleVolumeFrameType
3937                     (mri_dst, x,  y, z, f, SAMPLE_NEAREST, &dst) ;
3938                   MRIsetVoxVal
3939                     (mri_dst, x, y, z, f, (dst*dof+src)/(Real)(dof+1))  ;
3940                 }
3941             }
3942         }
3943     }
3944   return(mri_dst) ;
3945 }
3946 /*-----------------------------------------------------
3947   Parameters:
3948 
3949   Returns value:
3950 
3951   Description
3952 
3953   ------------------------------------------------------*/
3954 MRI *
3955 MRImultiply(MRI *mri1, MRI *mri2, MRI *mri_dst)
3956 {
3957   int     width, height, depth, x, y, z ;
3958   float   f1, f2 ;
3959 
3960   width = mri1->width ;
3961   height = mri1->height ;
3962   depth = mri1->depth ;
3963 
3964   if (!mri_dst)
3965     {
3966       mri_dst = MRIalloc(width, height, depth, mri1->type) ;
3967       MRIcopyHeader(mri1, mri_dst) ;
3968     }
3969 
3970   for (z = 0 ; z < depth ; z++)
3971     {
3972       for (y = 0 ; y < height ; y++)
3973         {
3974           for (x = 0 ; x < width ; x++)
3975             {
3976               f1 = MRIgetVoxVal(mri1, x, y, z, 0) ;
3977               f2 = MRIgetVoxVal(mri2, x, y, z, 0) ;
3978               MRIsetVoxVal(mri_dst, x, y, z, 0, f1*f2) ;
3979             }
3980         }
3981     }
3982   return(mri_dst) ;
3983 }
3984 /*-----------------------------------------------------
3985   Parameters:
3986 
3987   Returns value:
3988 
3989   Description
3990 
3991   ------------------------------------------------------*/
3992 MRI *
3993 MRIscaleAndMultiply(MRI *mri1, float scale, MRI *mri2, MRI *mri_dst)
3994 {
3995   int     width, height, depth, x, y, z ;
3996   BUFTYPE *p1, *p2, *pdst ;
3997   float   out_val ;
3998 
3999   width = mri1->width ;
4000   height = mri1->height ;
4001   depth = mri1->depth ;
4002 
4003   if (!mri_dst)
4004     {
4005       mri_dst = MRIalloc(width, height, depth, mri1->type) ;
4006       MRIcopyHeader(mri1, mri_dst) ;
4007     }
4008 
4009   for (z = 0 ; z < depth ; z++)
4010     {
4011       for (y = 0 ; y < height ; y++)
4012         {
4013           p1 = mri1->slices[z][y] ;
4014           p2 = mri2->slices[z][y] ;
4015           pdst = mri_dst->slices[z][y] ;
4016           for (x = 0 ; x < width ; x++)
4017             {
4018               out_val = *p1++ * (*p2++/scale) ;
4019               if (out_val > 255)
4020                 out_val = 255 ;
4021               else if (out_val < 0)
4022                 out_val = 0 ;
4023               *pdst++ = (BUFTYPE)nint(out_val) ;
4024             }
4025         }
4026     }
4027   return(mri_dst) ;
4028 }
4029 /*-----------------------------------------------------
4030   Parameters:
4031 
4032   Returns value:
4033 
4034   Description
4035 
4036   ------------------------------------------------------*/
4037 MRI *
4038 MRIdivide(MRI *mri1, MRI *mri2, MRI *mri_dst)
4039 {
4040   int     width, height, depth, x, y, z ;
4041   BUFTYPE *p1, *p2, *pdst ;
4042 
4043   width = mri1->width ;
4044   height = mri1->height ;
4045   depth = mri1->depth ;
4046 
4047   if (!mri_dst)
4048     {
4049       mri_dst = MRIalloc(width, height, depth, mri1->type) ;
4050       MRIcopyHeader(mri1, mri_dst) ;
4051     }
4052 
4053   if (mri1->type != MRI_UCHAR || mri2->type != MRI_UCHAR)
4054     {
4055       Real val1, val2, dst ;
4056 
4057       for (z = 0 ; z < depth ; z++)
4058         {
4059           for (y = 0 ; y < height ; y++)
4060             {
4061               pdst = mri_dst->slices[z][y] ;
4062               for (x = 0 ; x < width ; x++)
4063                 {
4064                   if (x == Gx && y == Gy && z==Gz)
4065                     DiagBreak() ;
4066                   val1 = MRIgetVoxVal(mri1, x, y, z, 0) ;
4067                   val2 = MRIgetVoxVal(mri2, x, y, z, 0) ;
4068                   if  (FZERO(val2))
4069                     {
4070                       dst = FZERO(val1) ? 0 : 255 ;
4071                     }
4072                   else
4073                     dst = val1 / val2 ;
4074                   if (abs(dst) > 1000)
4075                     DiagBreak() ;
4076                   MRIsetVoxVal(mri_dst, x, y, z, 0, dst) ;
4077                 }
4078             }
4079         }
4080     }
4081   else   /* both UCHAR volumes */
4082     {
4083       for (z = 0 ; z < depth ; z++)
4084         {
4085           for (y = 0 ; y < height ; y++)
4086             {
4087               p1 = mri1->slices[z][y] ;
4088               p2 = mri2->slices[z][y] ;
4089               pdst = mri_dst->slices[z][y] ;
4090               for (x = 0 ; x < width ; x++)
4091                 {
4092                   if  (!*p2)
4093                     {
4094                       *pdst = FZERO(*p1) ? 0 : 255 ;
4095                       p2++ ;
4096                     }
4097                   else
4098                     *pdst++ = *p1++ / *p2++ ;
4099                 }
4100             }
4101         }
4102     }
4103   return(mri_dst) ;
4104 }
4105 /*-----------------------------------------------------
4106   MRIclone() - create a copy of an mri struct. Copies
4107   header info and allocs the pixel space (but does not
4108   copy pixel data).
4109   ------------------------------------------------------*/
4110 MRI *MRIclone(MRI *mri_src, MRI *mri_dst)
4111 {
4112   if (!mri_dst)
4113     mri_dst =
4114       MRIallocSequence(mri_src->width, mri_src->height,mri_src->depth,
4115                        mri_src->type, mri_src->nframes);
4116 
4117   MRIcopyHeader(mri_src, mri_dst) ;
4118   return(mri_dst) ;
4119 }
4120 /*---------------------------------------------------------------------
4121   MRIcloneSpace() - create a copy of an mri struct but allows user to
4122   set nframes (ie, all the spatial stuff is copied). Copies header
4123   info and allocs the pixel space (but does not copy pixel data).
4124   -------------------------------------------------------------------*/
4125 MRI *MRIcloneBySpace(MRI *mri_src, int nframes)
4126 {
4127   MRI *mri_dst;
4128   mri_dst = MRIallocSequence(mri_src->width, mri_src->height,mri_src->depth,
4129                              mri_src->type, nframes);
4130   MRIcopyHeader(mri_src, mri_dst) ;
4131   mri_dst->nframes = nframes;
4132   return(mri_dst) ;
4133 }
4134 /*-----------------------------------------------------
4135   Description
4136   Copy one MRI into another (including header info)
4137   ------------------------------------------------------*/
4138 MRI *
4139 MRIcloneRoi(MRI *mri_src, MRI *mri_dst)
4140 {
4141   int  w, h, d ;
4142 
4143   w = mri_src->width - mri_src->roi.x ;
4144   h = mri_src->height - mri_src->roi.y ;
4145   d = mri_src->depth - mri_src->roi.z ;
4146   mri_dst = MRIallocSequence(w, h, d, MRI_FLOAT, mri_src->nframes) ;
4147   MRIcopyHeader(mri_src, mri_dst) ;
4148   mri_dst->xstart = mri_src->xstart + mri_src->roi.x * mri_src->xsize ;
4149   mri_dst->ystart = mri_src->ystart + mri_src->roi.y * mri_src->ysize ;
4150   mri_dst->zstart = mri_src->zstart + mri_src->roi.z * mri_src->zsize ;
4151   mri_dst->xend = mri_src->xstart + w * mri_src->xsize ;
4152   mri_dst->yend = mri_src->ystart + h * mri_src->ysize ;
4153   mri_dst->zend = mri_src->zstart + d * mri_src->zsize ;
4154   return(mri_dst) ;
4155 }
4156 /*-----------------------------------------------------
4157   Parameters:
4158 
4159   Returns value:
4160 
4161   Description
4162   Copy one MRI into another (including header info and data)
4163   ------------------------------------------------------*/
4164 MRI *
4165 MRIcopy(MRI *mri_src, MRI *mri_dst)
4166 {
4167   int     width, height, depth, bytes, x, y, z, frame, val ;
4168   float   *fdst, *fsrc ;
4169   BUFTYPE *csrc, *cdst ;
4170   int     dest_ptype, *isrc;
4171   short   *ssrc, *sdst ;
4172 
4173   if (mri_src == mri_dst)
4174     return(mri_dst) ;
4175   width = mri_src->width ;
4176   height = mri_src->height ;
4177   depth = mri_src->depth ;
4178 
4179   if (!mri_dst)
4180     {
4181       if(mri_src->slices)
4182         mri_dst = MRIallocSequence(width, height, depth, mri_src->type,
4183                                    mri_src->nframes) ;
4184       else
4185         mri_dst = MRIallocHeader(width, height, depth, mri_src->type);
4186     }
4187   dest_ptype = mri_dst->ptype;
4188   MRIcopyHeader(mri_src, mri_dst) ;
4189   mri_dst->ptype = dest_ptype;
4190 
4191   if(!mri_src->slices)
4192     return(mri_dst);
4193 
4194   if (mri_src->type == mri_dst->type)
4195     {
4196       bytes = width ;
4197       switch (mri_src->type)
4198         {
4199         case MRI_UCHAR:
4200           bytes *= sizeof(BUFTYPE) ;
4201           break ;
4202         case MRI_SHORT:
4203           bytes *= sizeof(short);
4204           break;
4205         case MRI_FLOAT:
4206           bytes *= sizeof(float) ;
4207           break ;
4208         case MRI_INT:
4209           bytes *= sizeof(int) ;
4210           break ;
4211         case MRI_LONG:
4212           bytes *= sizeof(long) ;
4213           break ;
4214         }
4215 
4216       for (frame = 0 ; frame < mri_src->nframes ; frame++)
4217         {
4218           for (z = 0 ; z < depth ; z++)
4219             {
4220               for (y = 0 ; y < height ; y++)
4221                 {
4222                   memcpy(mri_dst->slices[z+frame*depth][y],
4223                          mri_src->slices[z+frame*depth][y], bytes) ;
4224                 }
4225             }
4226         }
4227     }
4228   else
4229     {
4230       switch (mri_src->type)
4231         {
4232         case MRI_FLOAT:
4233           switch (mri_dst->type)
4234             {
4235             case MRI_SHORT: /* float --> short */
4236               for (frame = 0 ; frame < mri_src->nframes ; frame++)
4237                 {
4238                   for (z = 0 ; z < depth ; z++)
4239                     {
4240                       for (y = 0 ; y < height ; y++)
4241                         {
4242                           sdst = &MRISseq_vox(mri_dst, 0, y, z, frame) ;
4243                           fsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
4244                           for (x = 0 ; x < width ; x++)
4245                             {
4246                               val = nint(*fsrc++) ;
4247                               *sdst++ = (short)val ;
4248                             }
4249                         }
4250                     }
4251                 }
4252               break ;
4253             case MRI_UCHAR:  /* float --> unsigned char */
4254               for (frame = 0 ; frame < mri_src->nframes ; frame++)
4255                 {
4256                   for (z = 0 ; z < depth ; z++)
4257                     {
4258                       for (y = 0 ; y < height ; y++)
4259                         {
4260                           cdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
4261                           fsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
4262                           for (x = 0 ; x < width ; x++)
4263                             {
4264                               val = nint(*fsrc++) ;
4265                               if (val > 255)
4266                                 val = 255 ;
4267                               *cdst++ = (BUFTYPE)val ;
4268                             }
4269                         }
4270                     }
4271                 }
4272               break ;
4273             default:
4274               ErrorReturn(NULL,
4275                           (ERROR_BADPARM,
4276                            "MRIcopy: src type %d & dst type %d unsupported",
4277                            mri_src->type, mri_dst->type)) ;
4278               break ;
4279             }
4280           break ;
4281         case MRI_UCHAR:
4282           switch (mri_dst->type)
4283             {
4284             case MRI_FLOAT:   /* unsigned char --> float */
4285               for (frame = 0 ; frame < mri_src->nframes ; frame++)
4286                 {
4287                   for (z = 0 ; z < depth ; z++)
4288                     {
4289                       for (y = 0 ; y < height ; y++)
4290                         {
4291                           fdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
4292                           csrc = &MRIseq_vox(mri_src, 0, y, z, frame) ;
4293                           for (x = 0 ; x < width ; x++)
4294                             *fdst++ = (float)*csrc++ ;
4295                         }
4296                     }
4297                 }
4298               break ;
4299             default:
4300               ErrorReturn(NULL,
4301                           (ERROR_BADPARM,
4302                            "MRIcopy: src type %d & dst type %d unsupported",
4303                            mri_src->type, mri_dst->type)) ;
4304               break ;
4305             }
4306           break ;
4307         case MRI_SHORT:
4308           switch (mri_dst->type)
4309             {
4310             case MRI_FLOAT:   /* short --> float */
4311               for (frame = 0 ; frame < mri_src->nframes ; frame++)
4312                 {
4313                   for (z = 0 ; z < depth ; z++)
4314                     {
4315                       for (y = 0 ; y < height ; y++)
4316                         {
4317                           fdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
4318                           ssrc = &MRISseq_vox(mri_src, 0, y, z, frame) ;
4319                           for (x = 0 ; x < width ; x++)
4320                             {
4321                               if (z == 113 && y == 143 && x == 161)
4322                                 DiagBreak() ;
4323                               *fdst++ = (float)*ssrc++ ;
4324                             }
4325                         }
4326                     }
4327                 }
4328               break ;
4329             case MRI_UCHAR:
4330               for (frame = 0 ; frame < mri_src->nframes ; frame++)
4331                 {
4332                   for (z = 0 ; z < depth ; z++)
4333                     {
4334                       for (y = 0 ; y < height ; y++)
4335                         {
4336                           cdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
4337                           ssrc = &MRISseq_vox(mri_src, 0, y, z, frame) ;
4338                           for (x = 0 ; x < width ; x++)
4339                             {
4340                               *cdst++ = (float)*ssrc++ ;
4341                             }
4342                         }
4343                     }
4344                 }
4345               break ;
4346             default:
4347               ErrorReturn(NULL,
4348                           (ERROR_BADPARM,
4349                            "MRIcopy: src type %d & dst type %d unsupported",
4350                            mri_src->type, mri_dst->type)) ;
4351               break ;
4352             }
4353           break ;
4354         case MRI_INT:
4355           switch (mri_dst->type)
4356             {
4357             case MRI_FLOAT:   /* unsigned char --> float */
4358               for (frame = 0 ; frame < mri_src->nframes ; frame++)
4359                 {
4360                   for (z = 0 ; z < depth ; z++)
4361                     {
4362                       for (y = 0 ; y < height ; y++)
4363                         {
4364                           fdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
4365                           isrc = &MRIIseq_vox(mri_src, 0, y, z, frame) ;
4366                           for (x = 0 ; x < width ; x++)
4367                             *fdst++ = (float)*isrc++ ;
4368                         }
4369                     }
4370                 }
4371               break ;
4372             default:
4373               ErrorReturn(NULL,
4374                           (ERROR_BADPARM,
4375                            "MRIcopy: src type %d & dst type %d unsupported",
4376                            mri_src->type, mri_dst->type)) ;
4377               break ;
4378             }
4379           break ;
4380         default:
4381           ErrorReturn(NULL,
4382                       (ERROR_BADPARM,
4383                        "MRIcopy: src type %d & dst type %d unsupported",
4384                        mri_src->type, mri_dst->type)) ;
4385           break ;  /* in case someone removes the errorreturn */
4386         }
4387     }
4388   return(mri_dst) ;
4389 }
4390 /*
4391    make MAX_INDEX way larger than it has to be. This will give
4392    some headroom for bad (e.g. poorly registered) images without
4393    sacrificing too much space.
4394 */
4395 #define MAX_INDEX    500
4396 /*-----------------------------------------------------
4397   Parameters:
4398 
4399   Returns value:
4400 
4401   Description
4402   allocate a lookup table that allows indices which
4403   are outside the image region.
4404   ------------------------------------------------------*/
4405 int
4406 MRIallocIndices(MRI *mri)
4407 {
4408   int width, height, depth, i ;
4409 
4410   width = mri->width ;
4411   height = mri->height ;
4412   depth = mri->depth ;
4413   mri->xi = (int *)calloc(width+2*MAX_INDEX, sizeof(int)) ;
4414   if (!mri->xi)
4415     ErrorExit(ERROR_NO_MEMORY,
4416               "MRIallocIndices: could not allocate %d elt index array",
4417               width+2*MAX_INDEX) ;
4418   mri->yi = (int *)calloc(height+2*MAX_INDEX, sizeof(int)) ;
4419   if (!mri->yi)
4420     ErrorExit(ERROR_NO_MEMORY,
4421               "MRIallocIndices: could not allocate %d elt index array",
4422               height+2*MAX_INDEX) ;
4423   mri->zi = (int *)calloc(depth+2*MAX_INDEX, sizeof(int)) ;
4424   if (!mri->zi)
4425     ErrorExit(ERROR_NO_MEMORY,
4426               "MRIallocIndices: could not allocate %d elt index array",
4427               depth+2*MAX_INDEX) ;
4428 
4429   /*
4430      indexing into these arrays returns valid pixel indices from
4431      -MAX_INDEX to width+MAX_INDEX
4432   */
4433   mri->xi += MAX_INDEX ;
4434   mri->yi += MAX_INDEX ;
4435   mri->zi += MAX_INDEX ;
4436   for (i = -MAX_INDEX ; i < width+MAX_INDEX ; i++)
4437     {
4438       if (i <= 0)
4439         mri->xi[i] = 0 ;
4440       else if (i >= width)
4441         mri->xi[i] = width-1 ;
4442       else
4443         mri->xi[i] = i ;
4444     }
4445   for (i = -MAX_INDEX ; i < height+MAX_INDEX ; i++)
4446     {
4447       if (i <= 0)
4448         mri->yi[i] = 0 ;
4449       else if (i >= height)
4450         mri->yi[i] = height-1 ;
4451       else
4452         mri->yi[i] = i ;
4453     }
4454   for (i = -MAX_INDEX ; i < depth+MAX_INDEX ; i++)
4455     {
4456       if (i <= 0)
4457         mri->zi[i] = 0 ;
4458       else if (i >= depth)
4459         mri->zi[i] = depth-1 ;
4460       else
4461         mri->zi[i] = i ;
4462     }
4463 
4464   return(NO_ERROR) ;
4465 }
4466 /*-----------------------------------------------------
4467   Parameters:
4468 
4469   Returns value:
4470 
4471   Description
4472   allocate an MRI data structure as well as space for
4473   the image data
4474   ------------------------------------------------------*/
4475 MRI *
4476 MRIallocSequence(int width, int height, int depth, int type, int nframes)
4477 {
4478   MRI     *mri ;
4479   int     slice, row, bpp ;
4480   BUFTYPE *buf ;
4481 
4482   mris_alloced++ ;
4483 
4484   if ((width <= 0) || (height <= 0) || (depth <= 0))
4485     ErrorReturn(NULL,
4486                 (ERROR_BADPARM, "MRIalloc(%d, %d, %d): bad parm",
4487                  width, height, depth)) ;
4488 #if 1
4489   mri = MRIallocHeader(width, height, depth, type) ;
4490   MRIinitHeader(mri) ;
4491 #else
4492   mri = (MRI *)calloc(1, sizeof(MRI)) ;
4493   if (!mri)
4494     ErrorExit(ERROR_NO_MEMORY, "MRIalloc: could not allocate MRI\n") ;
4495 
4496   mri->scale = 1 ;
4497   mri->height = height ;
4498   mri->width = width ;
4499   mri->yinvert = 1 ;
4500   mri->depth = depth ;
4501   mri->type = type ;
4502 #endif
4503   mri->nframes = nframes ;
4504   MRIallocIndices(mri) ;
4505   mri->slices = (BUFTYPE ***)calloc(depth*nframes, sizeof(BUFTYPE **)) ;
4506   if (!mri->slices)
4507     ErrorExit(ERROR_NO_MEMORY,
4508               "MRIalloc: could not allocate %d slices\n", mri->depth) ;
4509 
4510   for (slice = 0 ; slice < depth*nframes ; slice++)
4511     {
4512       /* allocate pointer to array of rows */
4513       mri->slices[slice] = (BUFTYPE **)calloc(mri->height, sizeof(BUFTYPE *)) ;
4514       if (!mri->slices[slice])
4515         ErrorExit
4516           (ERROR_NO_MEMORY,
4517            "MRIalloc(%d, %d, %d): could not allocate "
4518            "%d bytes for %dth slice\n",
4519            height, width, depth, mri->height*sizeof(BUFTYPE *), slice) ;
4520 
4521 #if USE_ELECTRIC_FENCE
4522       switch (mri->type)
4523         {
4524         case MRI_BITMAP:
4525           bpp = 1 ;
4526           break ;
4527         case MRI_UCHAR:
4528           bpp = 8 ;
4529           break ;
4530         case MRI_TENSOR:
4531         case MRI_FLOAT:
4532           bpp = sizeof(float) * 8 ;
4533           break ;
4534         case MRI_INT:
4535           bpp = sizeof(int) * 8 ;
4536           break ;
4537         case MRI_SHORT:
4538           bpp = sizeof(short) * 8 ;
4539           break ;
4540         case MRI_LONG:
4541           bpp = sizeof(long) * 8 ;
4542           break ;
4543         default:
4544           ErrorReturn(NULL,
4545                       (ERROR_BADPARM,
4546                        "MRIalloc(%d, %d, %d, %d): unknown type",
4547                        width, height, depth, mri->type)) ;
4548           break ;
4549         }
4550       bpp /= 8 ;
4551       buf = (BUFTYPE *)calloc((mri->width*mri->height*bpp), 1) ;
4552       if (buf == NULL)
4553         ErrorExit
4554           (ERROR_NO_MEMORY,
4555            "MRIalloc(%d, %d, %d): could not allocate "
4556            "%d bytes for %dth slice\n",
4557            height, width, depth, (mri->width*mri->height*bpp), slice) ;
4558       for (row = 0 ; row < mri->height ; row++)
4559         {
4560           mri->slices[slice][row] = buf+(row*mri->width*bpp) ;
4561         }
4562 #else
4563       /* allocate each row */
4564       for (row = 0 ; row < mri->height ; row++)
4565         {
4566           switch (mri->type)
4567             {
4568             case MRI_BITMAP:
4569               mri->slices[slice][row] =
4570                 (BUFTYPE*)calloc(mri->width/8,sizeof(BUFTYPE));
4571               break ;
4572             case MRI_UCHAR:
4573               mri->slices[slice][row] =
4574                 (BUFTYPE*)calloc(mri->width,sizeof(BUFTYPE));
4575               break ;
4576             case MRI_TENSOR:
4577             case MRI_FLOAT:
4578               mri->slices[slice][row] =
4579                 (BUFTYPE *)calloc(mri->width, sizeof(float));
4580               break ;
4581             case MRI_INT:
4582               mri->slices[slice][row] =
4583                 (BUFTYPE *)calloc(mri->width, sizeof(int)) ;
4584               break ;
4585             case MRI_SHORT:
4586               mri->slices[slice][row] =
4587                 (BUFTYPE *)calloc(mri->width, sizeof(short));
4588               break ;
4589             case MRI_LONG:
4590               mri->slices[slice][row] =
4591                 (BUFTYPE *)calloc(mri->width, sizeof(long)) ;
4592               break ;
4593             default:
4594               ErrorReturn(NULL,
4595                           (ERROR_BADPARM,
4596                            "MRIalloc(%d, %d, %d, %d): unknown type",
4597                            width, height, depth, mri->type)) ;
4598               break ;
4599             }
4600 
4601           if (!mri->slices[slice][row])
4602             ErrorExit
4603               (ERROR_NO_MEMORY,
4604                "MRIalloc(%d,%d,%d): could not allocate "
4605                "%dth row in %dth slice\n",
4606                width,height,depth, slice, row) ;
4607         }
4608 #endif
4609     }
4610 
4611   return(mri) ;
4612 }
4613 /*-----------------------------------------------------
4614   Parameters:
4615 
4616   Returns value:
4617 
4618   Description
4619   allocate an MRI data structure but not space for
4620   the image data
4621   ------------------------------------------------------*/
4622 MRI *
4623 MRIallocHeader(int width, int height, int depth, int type)
4624 {
4625   MRI  *mri ;
4626 
4627   mri = (MRI *)calloc(1, sizeof(MRI)) ;
4628   if (!mri)
4629     ErrorExit(ERROR_NO_MEMORY, "MRIalloc: could not allocate MRI\n") ;
4630 
4631   mri->imnr0 = 1 ;
4632   mri->imnr1 = depth;
4633   mri->fov = width ;
4634   mri->thick = 1.0 ;
4635   mri->scale = 1 ;
4636   mri->roi.dx = mri->width = width ;
4637   mri->roi.dy = mri->height = height ;
4638   mri->roi.dz = mri->depth = depth ;
4639   mri->yinvert = 1 ;
4640   mri->xsize = mri->ysize = mri->zsize = 1 ;
4641   mri->type = type ;
4642   mri->nframes = 1 ;
4643   mri->xi = mri->yi = mri->zi = NULL ;
4644   mri->slices = NULL ;
4645   mri->ps = 1 ;
4646   mri->xstart = -mri->width/2.0 ;
4647   mri->xend = mri->width/2.0 ;
4648   mri->ystart = -mri->height/2.0 ;
4649   mri->yend = mri->height/2.0 ;
4650   mri->zstart = -mri->depth/2.0 ;
4651   mri->zend = mri->depth/2 ;
4652   //
4653   mri->x_r = -1;
4654   mri->x_a = 0.;
4655   mri->x_s = 0.;
4656   //
4657   mri->y_r = 0.;
4658   mri->y_a = 0.;
4659   mri->y_s = -1;
4660   //
4661   mri->z_r = 0.;
4662   mri->z_a = 1.;
4663   mri->z_s = 0.;
4664   //
4665   mri->c_r = mri->c_a = mri->c_s = 0.0;
4666   mri->ras_good_flag = 0;
4667   mri->brightness = 1;
4668   mri->register_mat = NULL;
4669   mri->subject_name[0] = '\0';
4670   mri->path_to_t1[0] = '\0';
4671   mri->fname_format[0] = '\0';
4672   mri->gdf_image_stem[0] = '\0';
4673   mri->tag_data = NULL;
4674   mri->tag_data_size = 0;
4675 
4676   mri->i_to_r__ = extract_i_to_r(mri);
4677   mri->r_to_i__ = extract_r_to_i(mri);
4678 
4679   return(mri) ;
4680 }
4681 /*-----------------------------------------------------
4682   Parameters:
4683 
4684   Returns value:
4685 
4686   Description
4687   allocate an MRI data structure as well as space for
4688   the image data
4689   ------------------------------------------------------*/
4690 MRI *
4691 MRIalloc(int width, int height, int depth, int type)
4692 {
4693   return(MRIallocSequence(width, height, depth, type, 1)) ;
4694 }
4695 /*-----------------------------------------------------
4696   Parameters:
4697 
4698   Returns value:
4699 
4700   Description
4701   Free and MRI data structure and all its attached memory
4702   ------------------------------------------------------*/
4703 int
4704 MRIfree(MRI **pmri)
4705 {
4706   MRI *mri ;
4707   int slice, i ;
4708 #if !USE_ELECTRIC_FENCE
4709   int  row ;
4710 #endif
4711 
4712   mris_alloced-- ;
4713   mri = *pmri ;
4714   if (!mri)
4715     ErrorReturn(ERROR_BADPARM, (ERROR_BADPARM, "MRIfree: null pointer\n")) ;
4716 
4717   if (mri->xi)
4718     free(mri->xi-MAX_INDEX) ;
4719   if (mri->yi)
4720     free(mri->yi-MAX_INDEX) ;
4721   if (mri->zi)
4722     free(mri->zi-MAX_INDEX) ;
4723 
4724   if (mri->slices)
4725     {
4726       for (slice = 0 ; slice < mri->depth*mri->nframes ; slice++)
4727         {
4728           if (mri->slices[slice])
4729             {
4730 #if USE_ELECTRIC_FENCE
4731               free(mri->slices[slice][0]) ;
4732 #else
4733               for (row = 0 ; row < mri->height ; row++)
4734                 free(mri->slices[slice][row]) ;
4735 #endif
4736               free(mri->slices[slice]) ;
4737             }
4738         }
4739       free(mri->slices) ;
4740     }
4741 
4742   if (mri->free_transform)
4743     delete_general_transform(&mri->transform) ;
4744 
4745   if(mri->register_mat != NULL)
4746     MatrixFree(&(mri->register_mat));
4747 
4748   if (mri->i_to_r__)
4749     MatrixFree(&mri->i_to_r__);
4750   if (mri->r_to_i__)
4751     MatrixFree(&mri->r_to_i__);
4752 
4753   for (i = 0 ; i < mri->ncmds ; i++)
4754     free(mri->cmdlines[i]) ;
4755 
4756   free(mri) ;
4757   *pmri = NULL ;
4758 
4759   return(NO_ERROR) ;
4760 }
4761 /*-----------------------------------------------------
4762   Parameters:
4763 
4764   Returns value:
4765 
4766   Description
4767   Free and MRI data structure and all its attached memory
4768   ------------------------------------------------------*/
4769 int
4770 MRIfreeFrames(MRI *mri, int start_frame)
4771 {
4772   int slice, row, end_frame ;
4773 
4774   end_frame = mri->nframes-1 ;
4775   if (!mri)
4776     ErrorReturn(ERROR_BADPARM, (ERROR_BADPARM, "MRIfree: null pointer\n")) ;
4777 
4778   if (mri->slices)
4779     {
4780       for (slice = start_frame*mri->depth ;
4781            slice < mri->depth*end_frame ; slice++)
4782         {
4783           if (mri->slices[slice])
4784             {
4785               for (row = 0 ; row < mri->height ; row++)
4786                 free(mri->slices[slice][row]) ;
4787               free(mri->slices[slice]) ;
4788             }
4789         }
4790     }
4791 
4792   mri->nframes -= (end_frame-start_frame+1) ;
4793   return(NO_ERROR) ;
4794 }
4795 /*-----------------------------------------------------
4796   Parameters:
4797 
4798   Returns value:
4799 
4800   Description
4801   Dump the MRI header to a file
4802   ------------------------------------------------------*/
4803 int
4804 MRIdump(MRI *mri, FILE *fp)
4805 {
4806   fprintf(fp, "%6.6s = %s\n", "fname", mri->fname);
4807   fprintf(fp, "%6.6s = %d\n", "height", mri->height);
4808   fprintf(fp, "%6.6s = %d\n", "width", mri->width);
4809   fprintf(fp, "%6.6s = %d\n", "depth", mri->depth);
4810   fprintf(fp, "%6.6s = %d\n", "nframes", mri->nframes);
4811   fprintf(fp, "%6.6s = %d\n", "imnr0", mri->imnr0);
4812   fprintf(fp, "%6.6s = %d\n", "imnr1", mri->imnr1);
4813   fprintf(fp, "%6.6s = %d\n", "xnum", mri->width);
4814   fprintf(fp, "%6.6s = %d\n", "ynum", mri->height);
4815   fprintf(fp, "%6.6s = %f\n", "fov", mri->fov);
4816   fprintf(fp, "%6.6s = %f\n", "thick", mri->thick);
4817   fprintf(fp, "%6.6s = %f\n", "xstart", mri->xstart); /* strtx */
4818   fprintf(fp, "%6.6s = %f\n", "xend", mri->xend); /* endx */
4819   fprintf(fp, "%6.6s = %f\n", "ystart", mri->ystart); /* strty */
4820   fprintf(fp, "%6.6s = %f\n", "yend", mri->yend); /* endy */
4821   fprintf(fp, "%6.6s = %f\n", "zstart", mri->zstart); /* strtz */
4822   fprintf(fp, "%6.6s = %f\n", "zend", mri->zend); /* endz */
4823   fprintf(fp, "%6.6s = %d\n", "type", mri->type);
4824   fprintf(fp, "%6.6s = %f\n", "xsize", mri->xsize);
4825   fprintf(fp, "%6.6s = %f\n", "ysize", mri->ysize);
4826   fprintf(fp, "%6.6s = %f\n", "zsize", mri->zsize);
4827   fprintf(fp, "%6.6s = %f %f %f\n", "x ras", mri->x_r, mri->x_a, mri->x_s);
4828   fprintf(fp, "%6.6s = %f %f %f\n", "y ras", mri->y_r, mri->y_a, mri->y_s);
4829   fprintf(fp, "%6.6s = %f %f %f\n", "z ras", mri->z_r, mri->z_a, mri->z_s);
4830   fprintf(fp, "%6.6s = %f %f %f\n", "c ras", mri->c_r, mri->c_a, mri->c_s);
4831   fprintf(fp, "%s = %f\n", "det(xyz_ras)", MRIvolumeDeterminant(mri));
4832   fprintf(fp, "%s = %d\n", "ras_good_flag", mri->ras_good_flag);
4833   fprintf(fp, "%s = %d\n", "brightness", mri->brightness);
4834   fprintf(fp, "%s = %s\n", "subject_name", mri->subject_name);
4835   fprintf(fp, "%s = %s\n", "path_to_t1", mri->path_to_t1);
4836   fprintf(fp, "%s = %s\n", "fname_format", mri->fname_format);
4837   if(mri->register_mat != NULL)
4838     {
4839       fprintf(fp, "%s = \n", "register_mat");
4840       MatrixPrint(fp, mri->register_mat);
4841     }
4842   return(NO_ERROR) ;
4843 }
4844 /*-----------------------------------------------------
4845   Parameters:
4846 
4847   Returns value:
4848 
4849   Description
4850   Dump the non-zero elements of an MRI buffer to a file
4851   ------------------------------------------------------*/
4852 int
4853 MRIdumpBuffer(MRI *mri, FILE *fp)
4854 {
4855   int  x, y, z ;
4856 
4857   for (z = 0 ; z < mri->depth ; z++)
4858     {
4859       for (y = 0 ; y < mri->height ; y++)
4860         {
4861           for (x = 0 ; x < mri->width ; x++)
4862             {
4863               switch (mri->type)
4864                 {
4865                 case MRI_UCHAR:
4866                   if (!FZERO(mri->slices[z][y][x]))
4867                     fprintf
4868                       (fp,
4869                        "[%d][%d][%d]: %d\n",
4870                        x,y,z,(int)mri->slices[z][y][x]);
4871                   break ;
4872                 case MRI_FLOAT:
4873                   /*          if (!FZERO(MRIFvox(mri,x,y,z)))*/
4874                   fprintf
4875                     (fp,
4876                      "[%d][%d][%d]: %2.3f\n",
4877                      x,y,z, MRIFvox(mri,x,y,z));
4878                   break ;
4879                 }
4880             }
4881         }
4882     }
4883   return(NO_ERROR) ;
4884 }
4885 /*-----------------------------------------------------
4886   Parameters:
4887 
4888   Returns value:
4889 
4890   Description
4891   Find the peak intensity in an MRI image
4892   ------------------------------------------------------*/
4893 int
4894 MRIpeak(MRI *mri, int *px, int *py, int *pz)
4895 {
4896   int      max_row, max_col, max_slice, row, col, slice, width, height, depth ;
4897   BUFTYPE  val, max_val, *im ;
4898   long     lval, lmax_val, *lim ;
4899   int      ival, imax_val, *iim ;
4900   float    fval, fmax_val, *fim ;
4901 
4902   max_val = 0 ;
4903   lmax_val = 0L ;
4904   imax_val = 0 ;
4905   fmax_val = 0.0f ;
4906   max_row = max_col = max_slice = -1 ;   /* to prevent compiler warning */
4907   width = mri->width ;
4908   height = mri->height ;
4909   depth = mri->depth ;
4910   for (slice = 0 ; slice < depth ; slice++)
4911     {
4912       for (row = 0 ; row < height ; row++)
4913         {
4914           switch (mri->type)
4915             {
4916             case MRI_UCHAR:
4917               im = mri->slices[slice][row] ;
4918               for (col = 0 ; col < width ; col++)
4919                 {
4920                   val = *im++ ;
4921                   if (val > max_val)
4922                     {
4923                       max_val = val ;
4924                       max_row = row ;
4925                       max_col = col ;
4926                       max_slice = slice ;
4927                     }
4928                 }
4929               break ;
4930             case MRI_LONG:
4931               lim = (long *)mri->slices[slice][row] ;
4932               for (col = 0 ; col < width ; col++)
4933                 {
4934                   lval = *lim++ ;
4935                   if (lval > lmax_val)
4936                     {
4937                       lmax_val = lval ;
4938                       max_row = row ;
4939                       max_col = col ;
4940                       max_slice = slice ;
4941                     }
4942                 }
4943               break ;
4944             case MRI_FLOAT:
4945               fim = (float *)mri->slices[slice][row] ;
4946               for (col = 0 ; col < width ; col++)
4947                 {
4948                   fval = *fim++ ;
4949                   if (fval > fmax_val)
4950                     {
4951                       fmax_val = fval ;
4952                       max_row = row ;
4953                       max_col = col ;
4954                       max_slice = slice ;
4955                     }
4956                 }
4957               break ;
4958             case MRI_INT:
4959               iim = (int *)mri->slices[slice][row] ;
4960               for (col = 0 ; col < width ; col++)
4961                 {
4962                   ival = *iim++ ;
4963                   if (ival > imax_val)
4964                     {
4965                       imax_val = ival ;
4966                       max_row = row ;
4967                       max_col = col ;
4968                       max_slice = slice ;
4969                     }
4970                 }
4971               break ;
4972             }
4973         }
4974     }
4975 
4976   *px = max_col ;
4977   *py = max_row ;
4978   *pz = max_slice ;
4979   return(NO_ERROR) ;
4980 }
4981 /*--------------------------------------------------------------
4982   Description: Copy the header information from one MRI into another.
4983   Does not copy the dimension lengths, only the geometry, pulse seq,
4984   etc.
4985   ------------------------------------------------------*/
4986 int MRIcopyHeader(MRI *mri_src, MRI *mri_dst)
4987 {
4988   int i ;
4989 
4990   mri_dst->dof = mri_src->dof ;
4991   mri_dst->mean = mri_src->mean ;
4992   mri_dst->xsize = mri_src->xsize ;
4993   mri_dst->ysize = mri_src->ysize ;
4994   mri_dst->zsize = mri_src->zsize ;
4995   if (mri_src->linear_transform)
4996     {
4997       copy_general_transform(&mri_src->transform, &mri_dst->transform) ;
4998       mri_dst->linear_transform = mri_src->linear_transform ;
4999       mri_dst->inverse_linear_transform = mri_src->inverse_linear_transform ;
5000       mri_dst->linear_transform =
5001         get_linear_transform_ptr(&mri_dst->transform) ;
5002       mri_dst->inverse_linear_transform =
5003         get_inverse_linear_transform_ptr(&mri_dst->transform) ;
5004       mri_dst->free_transform = 1 ;
5005     }
5006   strcpy(mri_dst->transform_fname, mri_src->transform_fname) ;
5007   if (mri_dst->depth == mri_src->depth)
5008     {
5009       mri_dst->imnr0 = mri_src->imnr0 ;
5010       mri_dst->imnr1 = mri_src->imnr1 ;
5011     }
5012   mri_dst->ptype = mri_src->ptype ;
5013   mri_dst->fov = mri_src->fov ;
5014   mri_dst->thick = mri_src->thick ;
5015   mri_dst->ps = mri_src->ps ;
5016   mri_dst->location = mri_src->location ;
5017   mri_dst->xstart = mri_src->xstart ;
5018   mri_dst->xend = mri_src->xend ;
5019   mri_dst->ystart = mri_src->ystart ;
5020   mri_dst->yend = mri_src->yend ;
5021   mri_dst->zstart = mri_src->zstart ;
5022   mri_dst->zend = mri_src->zend ;
5023   mri_dst->flip_angle = mri_src->flip_angle ;
5024   mri_dst->tr = mri_src->tr ;
5025   mri_dst->te = mri_src->te ;
5026   mri_dst->ti = mri_src->ti ;
5027   strcpy(mri_dst->fname, mri_src->fname) ;
5028   mri_dst->x_r = mri_src->x_r;
5029   mri_dst->x_a = mri_src->x_a;
5030   mri_dst->x_s = mri_src->x_s;
5031   mri_dst->y_r = mri_src->y_r;
5032   mri_dst->y_a = mri_src->y_a;
5033   mri_dst->y_s = mri_src->y_s;
5034   mri_dst->z_r = mri_src->z_r;
5035   mri_dst->z_a = mri_src->z_a;
5036   mri_dst->z_s = mri_src->z_s;
5037   mri_dst->c_r = mri_src->c_r;
5038   mri_dst->c_a = mri_src->c_a;
5039   mri_dst->c_s = mri_src->c_s;
5040   mri_dst->ras_good_flag = mri_src->ras_good_flag;
5041 
5042   mri_dst->brightness = mri_src->brightness;
5043   if(mri_src->register_mat != NULL)
5044     MatrixCopy(mri_src->register_mat, mri_dst->register_mat);
5045   else
5046     mri_dst->register_mat = NULL;
5047   strcpy(mri_dst->subject_name, mri_src->subject_name);
5048   strcpy(mri_dst->path_to_t1, mri_src->path_to_t1);
5049   strcpy(mri_dst->fname_format, mri_src->fname_format);
5050 
5051   strcpy(mri_dst->gdf_image_stem, mri_src->gdf_image_stem);
5052 
5053   mri_dst->i_to_r__ = MatrixCopy(mri_src->i_to_r__, mri_dst->i_to_r__);
5054   mri_dst->r_to_i__ = MatrixCopy(mri_src->r_to_i__, mri_dst->r_to_i__);
5055 
5056   for (i = 0 ; i < mri_src->ncmds ; i++)
5057     {
5058       mri_dst->cmdlines[i] =
5059         (char *)calloc(strlen(mri_src->cmdlines[i])+1, sizeof(char)) ;
5060       strcpy(mri_dst->cmdlines[i], mri_src->cmdlines[i]) ;
5061     }
5062   mri_dst->ncmds = mri_src->ncmds ;
5063   return(NO_ERROR) ;
5064 }
5065 /*-----------------------------------------------------
5066   Parameters:
5067 
5068   Returns value:
5069 
5070   Description
5071   Translate the MRI image mri_src by the vector
5072   dx, dy, dz  and store the result in mri_dst.
5073   ------------------------------------------------------*/
5074 MRI *
5075 MRItranslate(MRI *mri_src, MRI *mri_dst, double dx, double dy, double dz)
5076 {
5077   int      y1, y2, y3, width, height, depth ;
5078   BUFTYPE *pdst ;
5079   Real     x1, x2, x3, val ;
5080 
5081   width = mri_src->width ;
5082   height = mri_src->height ;
5083   depth = mri_src->depth ;
5084   if (!mri_dst)
5085     mri_dst = MRIclone(mri_src, NULL) ;
5086   else
5087     MRIclear(mri_dst) ;
5088 
5089   for (y3 = 0 ; y3 < depth ; y3++)
5090     {
5091       x3 = (Real)y3 - dz ;
5092       if (x3 < 0 || x3 >= depth)
5093         continue ;
5094 
5095       for (y2 = 0 ; y2 < height ; y2++)
5096         {
5097           x2 = (Real)y2 - dy ;
5098           if (x2 < 0 || x2 >= height)
5099             continue ;
5100 
5101           pdst = &MRIvox(mri_dst, 0, y2, y3) ;
5102           for (y1 = 0 ; y1 < width ; y1++, pdst++)
5103             {
5104               x1 = (Real)y1 - dx ;
5105               if (x1 >= 0 && x1 < width)
5106                 {
5107                   MRIsampleVolume(mri_src, x1, x2, x3, &val) ;
5108                   *pdst = (BUFTYPE)nint(val) ;
5109                 }
5110             }
5111         }
5112     }
5113 
5114   mri_dst->ras_good_flag = 0;
5115 
5116   return(mri_dst) ;
5117 }
5118 /*-----------------------------------------------------
5119   Parameters:
5120 
5121   Returns value:
5122 
5123   Description
5124   Rotate mri_src around the Y axis and return the
5125   result in mri_dst
5126   ------------------------------------------------------*/
5127 MRI *
5128 MRIrotateX(MRI *mri_src, MRI *mri_dst, float x_angle)
5129 {
5130   int    width, height, depth ;
5131   MATRIX *m, *mO ;
5132 
5133   width = mri_src->width ;
5134   height = mri_src->height ;
5135   depth = mri_src->depth ;
5136   if (!mri_dst)
5137     mri_dst = MRIclone(mri_src, NULL) ;
5138   else
5139     MRIclear(mri_dst) ;
5140 
5141   m = MatrixAllocRotation(3, x_angle, X_ROTATION) ;
5142 
5143   mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5144   mO->rptr[1][1] = mri_src->width / 2 ;
5145   mO->rptr[2][1] = mri_src->height / 2 ;
5146   mO->rptr[3][1] = mri_src->depth / 2 ;
5147 
5148   /* build rotation matrix */
5149   mri_dst = MRIrotate(mri_src, NULL, m, mO) ;
5150   MatrixFree(&m) ;
5151   MatrixFree(&mO) ;
5152 
5153   mri_dst->ras_good_flag = 0;
5154 
5155   return(mri_dst) ;
5156 }
5157 /*-----------------------------------------------------
5158   Parameters:
5159 
5160   Returns value:
5161 
5162   Description
5163   Rotate mri_src around the Y axis and return the
5164   result in mri_dst
5165   ------------------------------------------------------*/
5166 MRI *
5167 MRIrotateY(MRI *mri_src, MRI *mri_dst, float y_angle)
5168 {
5169   int    width, height, depth ;
5170   MATRIX *m, *mO ;
5171 
5172   width = mri_src->width ;
5173   height = mri_src->height ;
5174   depth = mri_src->depth ;
5175   if (!mri_dst)
5176     mri_dst = MRIclone(mri_src, NULL) ;
5177   else
5178     MRIclear(mri_dst) ;
5179 
5180   /* origin of coordinate system */
5181   mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5182   mO->rptr[1][1] = mri_src->width / 2 ;
5183   mO->rptr[2][1] = mri_src->height / 2 ;
5184   mO->rptr[3][1] = mri_src->depth / 2 ;
5185 
5186   m = MatrixAllocRotation(3, y_angle, Y_ROTATION) ;
5187 
5188   /* build rotation matrix */
5189   mri_dst = MRIrotate(mri_src, NULL, m, mO) ;
5190   MatrixFree(&m) ;
5191   MatrixFree(&mO) ;
5192 
5193   mri_dst->ras_good_flag = 0;
5194 
5195   return(mri_dst) ;
5196 }
5197 /*-----------------------------------------------------
5198   Parameters:
5199 
5200   Returns value:
5201 
5202   Description
5203   Rotate mri_src around the Z axis and return the
5204   result in mri_dst
5205   ------------------------------------------------------*/
5206 MRI *
5207 MRIrotateZ(MRI *mri_src, MRI *mri_dst, float z_angle)
5208 {
5209   int    width, height, depth ;
5210   MATRIX *m, *mO ;
5211 
5212   width = mri_src->width ;
5213   height = mri_src->height ;
5214   depth = mri_src->depth ;
5215   if (!mri_dst)
5216     mri_dst = MRIclone(mri_src, NULL) ;
5217   else
5218     MRIclear(mri_dst) ;
5219 
5220   m = MatrixAllocRotation(3, z_angle, Z_ROTATION) ;
5221   mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5222   mO->rptr[1][1] = mri_src->width / 2 ;
5223   mO->rptr[2][1] = mri_src->height / 2 ;
5224   mO->rptr[3][1] = mri_src->depth / 2 ;
5225 
5226   mri_dst = MRIrotate(mri_src, NULL, m, mO) ;
5227   MatrixFree(&m) ;
5228   MatrixFree(&mO) ;
5229 
5230   mri_dst->ras_good_flag = 0;
5231 
5232   return(mri_dst) ;
5233 }
5234 /*-----------------------------------------------------
5235   Parameters:
5236 
5237   Returns value:
5238 
5239   Description
5240   Rotate mri_src around the Y axis and return the
5241   result in mri_dst
5242   ------------------------------------------------------*/
5243 MRI *
5244 MRIrotateX_I(MRI *mri_src, MRI *mri_dst, float x_angle)
5245 {
5246   int    width, height, depth ;
5247   MATRIX *m ;
5248 
5249   width = mri_src->width ;
5250   height = mri_src->height ;
5251   depth = mri_src->depth ;
5252   if (!mri_dst)
5253     mri_dst = MRIclone(mri_src, NULL) ;
5254   else
5255     MRIclear(mri_dst) ;
5256 
5257   m = MatrixAllocRotation(3, x_angle, X_ROTATION) ;
5258 
5259   /* build rotation matrix */
5260   mri_dst = MRIrotate_I(mri_src, NULL, m, NULL) ;
5261   MatrixFree(&m) ;
5262 
5263   mri_dst->ras_good_flag = 0;
5264 
5265   return(mri_dst) ;
5266 }
5267 /*-----------------------------------------------------
5268   Parameters:
5269 
5270   Returns value:
5271 
5272   Description
5273   Rotate mri_src around the Y axis and return the
5274   result in mri_dst
5275   ------------------------------------------------------*/
5276 MRI *
5277 MRIrotateY_I(MRI *mri_src, MRI *mri_dst, float y_angle)
5278 {
5279   int    width, height, depth ;
5280   MATRIX *m ;
5281 
5282   width = mri_src->width ;
5283   height = mri_src->height ;
5284   depth = mri_src->depth ;
5285   if (!mri_dst)
5286     mri_dst = MRIclone(mri_src, NULL) ;
5287   else
5288     MRIclear(mri_dst) ;
5289 
5290   m = MatrixAllocRotation(3, y_angle, Y_ROTATION) ;
5291 
5292   /* build rotation matrix */
5293   mri_dst = MRIrotate_I(mri_src, NULL, m, NULL) ;
5294   MatrixFree(&m) ;
5295 
5296   mri_dst->ras_good_flag = 0;
5297 
5298   return(mri_dst) ;
5299 }
5300 /*-----------------------------------------------------
5301   Parameters:
5302 
5303   Returns value:
5304 
5305   Description
5306   Rotate mri_src around the Z axis and return the
5307   result in mri_dst
5308   ------------------------------------------------------*/
5309 MRI *
5310 MRIrotateZ_I(MRI *mri_src, MRI *mri_dst, float z_angle)
5311 {
5312   int    width, height, depth ;
5313   MATRIX *m ;
5314 
5315   width = mri_src->width ;
5316   height = mri_src->height ;
5317   depth = mri_src->depth ;
5318   if (!mri_dst)
5319     mri_dst = MRIclone(mri_src, NULL) ;
5320   else
5321     MRIclear(mri_dst) ;
5322 
5323   m = MatrixAllocRotation(3, z_angle, Z_ROTATION) ;
5324   mri_dst = MRIrotate_I(mri_src, NULL, m, NULL) ;
5325   MatrixFree(&m) ;
5326 
5327   mri_dst->ras_good_flag = 0;
5328 
5329   return(mri_dst) ;
5330 }
5331 /*-----------------------------------------------------
5332   Parameters:
5333 
5334   Returns value:
5335 
5336   Description
5337   Scale the MRI image mri_src by sx,sy,sz in the
5338   x, y, and z directions respectively.
5339   ------------------------------------------------------*/
5340 MRI *
5341 MRIscale(MRI *mri_src, MRI *mri_dst, float sx, float sy, float sz)
5342 {
5343   int    width, height, depth ;
5344   MATRIX *m ;
5345 
5346   width = mri_src->width ;
5347   height = mri_src->height ;
5348   depth = mri_src->depth ;
5349   if (!mri_dst)
5350     {
5351       mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
5352       MRIcopyHeader(mri_src, mri_dst) ;
5353     }
5354 
5355   m = MatrixAlloc(4, 4, MATRIX_REAL) ;
5356 
5357   /* build rotation matrix */
5358   m->rptr[1][1] = sx ;
5359   m->rptr[2][2] = sy ;
5360   m->rptr[3][3] = sz ;
5361   m->rptr[4][4] = 1.0 ;
5362   mri_dst = MRIlinearTransform(mri_src, NULL, m) ;
5363   MatrixFree(&m) ;
5364 
5365   mri_dst->ras_good_flag = 0;
5366 
5367   return(mri_dst) ;
5368 }
5369 /*-----------------------------------------------------
5370   Parameters:
5371 
5372   Returns value:
5373 
5374   Description
5375   Rotate about the point mO
5376   ------------------------------------------------------*/
5377 MRI *
5378 MRIrotate(MRI *mri_src, MRI *mri_dst, MATRIX *mR, MATRIX *mO)
5379 {
5380   int    x1, x2, x3, y1, y2, y3, width, height, depth, y1o, y2o, y3o, freeit ;
5381   MATRIX *mX, *mY ;   /* original and transformed coordinate systems */
5382   MATRIX *mRinv ;   /* inverse of R */
5383 
5384   mRinv = MatrixInverse(mR, NULL) ;
5385   if (!mRinv)
5386     ErrorReturn(NULL,(ERROR_BADPARM,"MRIrotate: rotation matrix is singular"));
5387 
5388   width = mri_src->width ;
5389   height = mri_src->height ;
5390   depth = mri_src->depth ;
5391   if (!mri_dst)
5392     mri_dst = MRIclone(mri_src, NULL) ;
5393   else
5394     MRIclear(mri_dst) ;
5395 
5396   if (!mO)
5397     {
5398       mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5399       mO->rptr[1][1] = mri_src->width / 2 ;
5400       mO->rptr[2][1] = mri_src->height / 2 ;
5401       mO->rptr[3][1] = mri_src->depth / 2 ;
5402       freeit = 1 ;
5403     }
5404   else
5405     freeit = 0 ;
5406 
5407   mX = MatrixAlloc(3, 1, MATRIX_REAL) ;  /* input coordinates */
5408   mY = MatrixAlloc(3, 1, MATRIX_REAL) ;  /* transformed coordinates */
5409 
5410 
5411   y1o = mO->rptr[1][1] ;
5412   y2o = mO->rptr[2][1] ;
5413   y3o = mO->rptr[3][1] ;
5414   for (y3 = 0 ; y3 < depth ; y3++)
5415     {
5416       mY->rptr[3][1] = y3 - y3o ;
5417       for (y2 = 0 ; y2 < height ; y2++)
5418         {
5419           mY->rptr[2][1] = y2 - y2o ;
5420           for (y1 = 0 ; y1 < width ; y1++)
5421             {
5422               mY->rptr[1][1] = y1 - y1o ;
5423               MatrixMultiply(mRinv, mY, mX) ;
5424               MatrixAdd(mX, mO, mX) ;
5425 
5426               /* should do bilinear interpolation here */
5427               x1 = nint(mX->rptr[1][1]) ;
5428               x2 = nint(mX->rptr[2][1]) ;
5429               x3 = nint(mX->rptr[3][1]) ;
5430               if (x1 >= 0 && x1 < width &&
5431                   x2 >= 0 && x2 < height &&
5432                   x3 >= 0 && x3 < depth)
5433                 mri_dst->slices[y3][y2][y1] = mri_src->slices[x3][x2][x1] ;
5434             }
5435         }
5436     }
5437 
5438   MatrixFree(&mX) ;
5439   MatrixFree(&mRinv) ;
5440   MatrixFree(&mY) ;
5441   if (freeit)
5442     MatrixFree(&mO) ;
5443 
5444   mri_dst->ras_good_flag = 0;
5445 
5446   return(mri_dst) ;
5447 }
5448 /*-----------------------------------------------------
5449   Parameters:
5450 
5451   Returns value:
5452 
5453   Description
5454   Rotate about the point mO using trilinear interpolation
5455   ------------------------------------------------------*/
5456 MRI *
5457 MRIrotate_I(MRI *mri_src, MRI *mri_dst, MATRIX *mR, MATRIX *mO)
5458 {
5459   int    y1, y2, y3, width, height, depth, y1o, y2o, y3o, freeit ;
5460   MATRIX *mX, *mY ;   /* original and transformed coordinate systems */
5461   MATRIX *mRinv ;   /* inverse of R */
5462   float  x1, x2, x3 ;
5463   Real   val ;
5464 
5465   mRinv = MatrixInverse(mR, NULL) ;
5466   if (!mRinv)
5467     ErrorReturn(NULL,(ERROR_BADPARM,
5468                       "MRIrotate_I: rotation matrix is singular"));
5469 
5470   width = mri_src->width ;
5471   height = mri_src->height ;
5472   depth = mri_src->depth ;
5473   if (!mri_dst)
5474     mri_dst = MRIclone(mri_src, NULL) ;
5475   else
5476     MRIclear(mri_dst) ;
5477 
5478   if (!mO)
5479     {
5480       mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5481       mO->rptr[1][1] = mri_src->width / 2 ;
5482       mO->rptr[2][1] = mri_src->height / 2 ;
5483       mO->rptr[3][1] = mri_src->depth / 2 ;
5484       freeit = 1 ;
5485     }
5486   else
5487     freeit = 0 ;
5488 
5489   mX = MatrixAlloc(3, 1, MATRIX_REAL) ;  /* input coordinates */
5490   mY = MatrixAlloc(3, 1, MATRIX_REAL) ;  /* transformed coordinates */
5491 
5492 
5493   y1o = mO->rptr[1][1] ;
5494   y2o = mO->rptr[2][1] ;
5495   y3o = mO->rptr[3][1] ;
5496   if (Gdiag == 99)
5497     MatrixPrint(stdout, mRinv) ;
5498   if (Gdiag == 99)
5499     MatrixPrint(stdout, mO) ;
5500   for (y3 = 0 ; y3 < depth ; y3++)
5501     {
5502       mY->rptr[3][1] = y3 - y3o ;
5503       for (y2 = 0 ; y2 < height ; y2++)
5504         {
5505           mY->rptr[2][1] = y2 - y2o ;
5506           for (y1 = 0 ; y1 < width ; y1++)
5507             {
5508               mY->rptr[1][1] = y1 - y1o ;
5509               MatrixMultiply(mRinv, mY, mX) ;
5510               MatrixAdd(mX, mO, mX) ;
5511 
5512               /* do trilinear interpolation here */
5513               x1 = mX->rptr[1][1] ;
5514               x2 = mX->rptr[2][1] ;
5515               x3 = mX->rptr[3][1] ;
5516 
5517               MRIsampleVolume(mri_src, x1, x2, x3, &val) ;
5518               mri_dst->slices[y3][y2][y1] = (BUFTYPE)nint(val) ;
5519             }
5520         }
5521     }
5522 
5523   MatrixFree(&mX) ;
5524   MatrixFree(&mRinv) ;
5525   MatrixFree(&mY) ;
5526   if (freeit)
5527     MatrixFree(&mO) ;
5528 
5529   mri_dst->ras_good_flag = 0;
5530 
5531   return(mri_dst) ;
5532 }
5533 /*-----------------------------------------------------
5534   Parameters:
5535 
5536   Returns value:
5537 
5538   Description
5539   Perform an affine coordinate transformation x' = Ax + B on
5540   the MRI image mri_src into mri_dst
5541   ------------------------------------------------------*/
5542 MRI *
5543 MRIaffine(MRI *mri_src, MRI *mri_dst, MATRIX *mA, MATRIX *mB)
5544 {
5545   int    x1, x2, x3, y1, y2, y3, width, height, depth ;
5546   MATRIX *mX, *mY ;   /* original and transformed coordinate systems */
5547 
5548   width = mri_src->width ;
5549   height = mri_src->height ;
5550   depth = mri_src->depth ;
5551   if (!mri_dst)
5552     {
5553       mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
5554       MRIcopyHeader(mri_src, mri_dst) ;
5555     }
5556 
5557   mX = MatrixAlloc(3, 1, MATRIX_REAL) ;  /* input coordinates */
5558   mY = MatrixAlloc(3, 1, MATRIX_REAL) ;  /* transformed coordinates */
5559 
5560   for (x3 = 0 ; x3 < depth ; x3++)
5561     {
5562       mX->rptr[3][1] = x3 ;
5563       for (x2 = 0 ; x2 < height ; x2++)
5564         {
5565           mX->rptr[2][1] = x2 ;
5566           for (x1 = 0 ; x1 < width ; x1++)
5567             {
5568               mX->rptr[1][1] = x1 ;
5569               if (mA)
5570                 MatrixMultiply(mA, mX, mY) ;
5571               else
5572                 MatrixCopy(mX, mY) ;
5573               if (mB)
5574                 MatrixAdd(mY, mB, mY) ;
5575               y1 = nint(mY->rptr[1][1]) ;
5576               y2 = nint(mY->rptr[2][1]) ;
5577               y3 = nint(mY->rptr[3][1]) ;
5578               if (y1 >= 0 && y1 < width &&
5579                   y2 >= 0 && y2 < height &&
5580                   y3 >= 0 && y3 < depth)
5581                 mri_dst->slices[y3][y2][y1] = mri_src->slices[x3][x2][x1] ;
5582             }
5583         }
5584     }
5585 
5586 
5587   MatrixFree(&mX) ;
5588   MatrixFree(&mY) ;
5589 
5590   mri_dst->ras_good_flag = 0;
5591 
5592   return(mri_dst) ;
5593 }
5594 /*-----------------------------------------------------
5595   Parameters:
5596 
5597   Returns value:
5598 
5599   Description
5600   Convert a slice of an MRI data structure into a HIPS image.
5601   ------------------------------------------------------*/
5602 IMAGE *
5603 MRItoImageView(MRI *mri, IMAGE *I, int slice, int view, int frame)
5604 {
5605   int      width, height, depth, x, y, yp, w, h, d,
5606     xm, ym, zm, format ;
5607   float    fmin, fmax ;
5608   Real     val ;
5609   int src_slice_direction;
5610   int xsign, ysign;
5611 
5612   xsign=ysign=1; // let compiler be satisfied
5613 
5614   src_slice_direction = getSliceDirection(mri);
5615   // only strict slice direction is supported
5616   if (src_slice_direction == MRI_UNDEFINED)
5617     ErrorReturn(NULL,
5618                 (ERROR_UNSUPPORTED,
5619                  "MRItoImageView(%d, %d): unsupported view/slice direction %d",
5620                  slice, view, src_slice_direction)) ;
5621 
5622   // generic routines to get the right axes
5623   //
5624   // should be able to do this in generic terms.
5625   // don't have time to do that
5626   //
5627   // Define the view to be the following:
5628   // coronal    = (-R, -S)
5629   // sagittal   = ( A, -S)
5630   // horizontal = (-R,  A)
5631   //
5632   // translate these direction into (x,y)
5633   d = w = h = xm = ym = zm = 0 ;  /* silly compiler warnings */
5634   width = mri->width ;
5635   height = mri->height ;
5636   depth = mri->depth ;
5637 
5638   switch(src_slice_direction)
5639     {
5640     case MRI_CORONAL: // x direction can be -R or R,
5641       // y direction can be -S or S, z direction can be -A or A
5642       //     +/-1  0  0
5643       //      0    0  +/-1
5644       //      0  +/-1 0
5645       switch(view)
5646         {
5647         case MRI_CORONAL:
5648           w = width; h = height; d = depth;
5649           xsign = (mri->x_r > 0) ? -1 : 1; ysign = (mri->y_s > 0) ? -1 : 1;
5650           break;
5651         case MRI_SAGITTAL:
5652           w = depth; h = height; d = width;
5653           xsign = (mri->z_a > 0) ?  1 : -1; ysign = (mri->y_s > 0) ? -1 : 1;
5654           break;
5655         case MRI_HORIZONTAL:
5656           w = width; h = depth;  d = height;
5657           xsign = (mri->x_r > 0) ? -1 : 1; ysign = (mri->z_a > 0) ? 1 : -1;
5658           break;
5659         }
5660       break;
5661     case MRI_SAGITTAL: // x direction can be -A or A,
5662       // y direction can be -S or S, z direction can be -R or R
5663       //    0    0   +/-1
5664       //  +/-1   0    0
5665       //    0  +/-1   0
5666       switch(view)
5667         {
5668         case MRI_CORONAL:
5669           w = depth; h = height; d = width;
5670           xsign =
5671             (mri->z_r > 0) ? -1 : 1; ysign = (mri->y_s > 0) ? -1 : 1;
5672           break;
5673         case MRI_SAGITTAL:
5674           w = width; h = height; d = depth;
5675           xsign = (mri->x_a > 0) ? 1 : -1; ysign = (mri->y_s > 0) ? -1 : 1;
5676           break;
5677         case MRI_HORIZONTAL:
5678           w = depth; h = width;  d = height;
5679           xsign = (mri->z_r > 0) ? -1 : 1; ysign = (mri->x_a > 0) ? 1 : -1;
5680           break;
5681         }
5682       break;
5683     case MRI_HORIZONTAL: // x direction can be -R or R,
5684       // y direction can be -A or A, z direction can be -S or S
5685       //   +/-1  0   0
5686       //    0   +/-1 0
5687       //    0    0  +/-1
5688       switch(view)
5689         {
5690         case MRI_CORONAL:
5691           w = width; h = depth; d = height;
5692           xsign = (mri->x_r > 0) ? -1 : 1; ysign = (mri->z_s > 0) ? -1 : 1;
5693           break;
5694         case MRI_SAGITTAL:
5695           w = height; h = depth; d = width;
5696           xsign = (mri->y_a > 0) ? 1 : -1; ysign = (mri->z_s > 0) ? -1 : 1;
5697           break;
5698         case MRI_HORIZONTAL:
5699           w = width; h = height;  d = depth;
5700           xsign = (mri->x_r > 0) ? -1 : 1; ysign = (mri->y_a > 0) ?  1 : -1;
5701           break;
5702         }
5703       break;
5704     default:
5705       ErrorReturn
5706         (NULL,
5707          (ERROR_UNSUPPORTED,
5708           "MRItoImageView(%d, %d): unsupported view/slice direction %d",
5709           slice, view, src_slice_direction)) ;
5710     }
5711   if (slice < 0 || slice >= d)
5712     ErrorReturn(NULL, (ERROR_BADPARM, "MRItoImageView: bad slice %d\n",slice));
5713 
5714 #if 0
5715   format = (mri->type == MRI_UCHAR) ? PFBYTE :
5716     mri->type == MRI_INT   ? PFINT :
5717     mri->type == MRI_FLOAT ? PFFLOAT :
5718     mri->type == MRI_SHORT ? PFFLOAT : PFBYTE ;
5719 #else
5720   format = PFBYTE ;
5721 #endif
5722 
5723   if (I && ((I->rows != h) || (I->cols != w) || (I->pixel_format != format)))
5724     {
5725       ImageFree(&I);
5726       I = NULL ;  /* must allocate a new one */
5727     }
5728   if (!I)
5729     I = ImageAlloc(h, w, format, 1) ;
5730 
5731   fmin = 10000000 ; fmax = -fmin ;
5732 
5733   // Image values assigned from MRI
5734   // we need to gert min and max in IMAGE
5735   for (y = 0 ; y < h ; y++)
5736     {
5737       for (x = 0 ; x < w ; x++)
5738         {
5739           switch(src_slice_direction)
5740             {
5741             case MRI_CORONAL:
5742               switch (view)   /* calculate coordinates in MR structure */
5743                 {
5744                 case MRI_CORONAL:
5745                   xm = (xsign> 0) ? x : (w - 1 -x);
5746                   ym = (ysign> 0) ? y : (h - 1 -y);
5747                   zm = slice ;
5748                   break ;
5749                 case MRI_SAGITTAL:
5750                   xm = slice ;
5751                   ym = (ysign>0) ? y : (h - 1 - y);
5752                   zm = (xsign>0) ? x : (w - 1 - x);
5753                   break ;
5754                 case MRI_HORIZONTAL:
5755                   xm = (xsign>0) ? x : (w - 1 - x);
5756                   ym = slice ;
5757                   zm = (ysign>0) ? y : (h - 1 - y);
5758                   break ;
5759                 }
5760               break;
5761             case MRI_SAGITTAL:
5762               switch (view)   /* calculate coordinates in MR structure */
5763                 {
5764                 case MRI_CORONAL:
5765                   xm = slice;
5766                   ym = (ysign>0) ? y : (h - 1 - y);
5767                   zm = (xsign>0) ? x : (w - 1 - x);
5768                   break ;
5769                 case MRI_SAGITTAL:
5770                   xm = (xsign>0) ? x : (w - 1 - x);
5771                   ym = (ysign>0) ? y : (h - 1 - y);
5772                   zm = slice ;
5773                   break ;
5774                 case MRI_HORIZONTAL:
5775                   xm = (ysign>0) ? y : (h - 1 - y);
5776                   ym = slice;
5777                   zm = (xsign>0) ? x : (w - 1 - x);
5778                   break ;
5779                 }
5780               break;
5781             case MRI_HORIZONTAL:
5782               switch (view)   /* calculate coordinates in MR structure */
5783                 {
5784                 case MRI_CORONAL:
5785                   xm = (xsign>0) ? x : (w - 1 - x);
5786                   ym = slice ;
5787                   zm = (ysign>0) ? y : (h - 1 - y);
5788                   break ;
5789                 case MRI_SAGITTAL:
5790                   xm = slice ;
5791                   ym = (xsign>0) ? x : (w - 1 - x);
5792                   zm = (ysign>0) ? y : (h - 1 - y);
5793                   break ;
5794                 case MRI_HORIZONTAL:
5795                   xm = (xsign>0) ? x : (w - 1 - x);
5796                   ym = (ysign>0) ? y : (h - 1 - y);
5797                   zm = slice ;
5798                   break ;
5799                 }
5800               break;
5801             }
5802           MRIsampleVolumeFrame(mri, xm, ym, zm, frame, &val) ;
5803           // check min max
5804           if (val > fmax)
5805             fmax = val ;
5806           if (val < fmin)
5807             fmin = val ;
5808         }
5809     }
5810   if (FZERO(fmax-fmin))
5811     ErrorReturn(I, (ERROR_BADPARM, "MRItoImageView: constant image")) ;
5812 
5813   // after all these calculation, we are going to do it again?
5814   for (y = 0 ; y < h ; y++)
5815     {
5816 
5817       for (x = 0 ; x < w ; x++)
5818         {
5819           switch(src_slice_direction)
5820             {
5821             case MRI_CORONAL:
5822               switch (view)   /* calculate coordinates in MR structure */
5823                 {
5824                 case MRI_CORONAL:
5825                   xm = (xsign> 0) ? x : (w - 1 -x);
5826                   ym = (ysign> 0) ? y : (h - 1 -y);
5827                   zm = slice ;
5828                   break ;
5829                 case MRI_SAGITTAL:
5830                   xm = slice ;
5831                   ym = (ysign>0) ? y : (h - 1 - y);
5832                   zm = (xsign>0) ? x : (w - 1 - x);
5833                   break ;
5834                 case MRI_HORIZONTAL:
5835                   xm = (xsign>0) ? x : (w - 1 - x);
5836                   ym = slice ;
5837                   zm = (ysign>0) ? y : (h - 1 - y);
5838                   break ;
5839                 }
5840               break;
5841             case MRI_SAGITTAL:
5842               switch (view)   /* calculate coordinates in MR structure */
5843                 {
5844                 case MRI_CORONAL:
5845                   xm = slice;
5846                   ym = (ysign>0) ? y : (h - 1 - y);
5847                   zm = (xsign>0) ? x : (w - 1 - x);
5848                   break ;
5849                 case MRI_SAGITTAL:
5850                   xm = (xsign>0) ? x : (w - 1 - x);
5851                   ym = (ysign>0) ? y : (h - 1 - y);
5852                   zm = slice ;
5853                   break ;
5854                 case MRI_HORIZONTAL:
5855                   xm = (ysign>0) ? y : (h - 1 - y);
5856                   ym = slice;
5857                   zm = (xsign>0) ? x : (w - 1 - x);
5858                   break ;
5859                 }
5860               break;
5861             case MRI_HORIZONTAL:
5862               switch (view)   /* calculate coordinates in MR structure */
5863                 {
5864                 case MRI_CORONAL:
5865                   xm = (xsign>0) ? x : (w - 1 - x);
5866                   ym = slice ;
5867                   zm = (ysign>0) ? y : (h - 1 - y);
5868                   break ;
5869                 case MRI_SAGITTAL:
5870                   xm = slice ;
5871                   ym = (xsign>0) ? x : (w - 1 - x);
5872                   zm = (ysign>0) ? y : (h - 1 - y);
5873                   break ;
5874                 case MRI_HORIZONTAL:
5875                   xm = (xsign>0) ? x : (w - 1 - x);
5876                   ym = (ysign>0) ? y : (h - 1 - y);
5877                   zm = slice ;
5878                   break ;
5879                 }
5880               break;
5881             }
5882           MRIsampleVolumeFrame(mri, xm, ym, zm, frame, &val) ;
5883           yp = h - (y+1) ;   /* hips coordinate system is inverted */
5884           *IMAGEpix(I, x, yp) = (byte)(255.0 * (val - fmin) / (fmax - fmin)) ;
5885         }
5886     }
5887 
5888   return(I) ;
5889 }
5890 /*-----------------------------------------------------
5891   Parameters:
5892 
5893   Returns value:
5894 
5895   Description
5896   Convert a slice of an MRI data structure into a HIPS image.
5897   ------------------------------------------------------*/
5898 IMAGE *
5899 MRItoImage(MRI *mri, IMAGE *I, int slice)
5900 {
5901   int           width, height, y, yp ;
5902 
5903   width = mri->width ;
5904   height = mri->height ;
5905   if (slice < 0 || slice >= mri->depth)
5906     ErrorReturn(NULL, (ERROR_BADPARM, "MRItoImage: bad slice %d\n", slice)) ;
5907 
5908   if (!I)
5909     {
5910       I = ImageAlloc(height, width,
5911                      mri->type == MRI_UCHAR ? PFBYTE :
5912                      mri->type == MRI_INT   ? PFINT :
5913                      mri->type == MRI_FLOAT ? PFFLOAT : PFBYTE, 1) ;
5914     }
5915 
5916   for (y = 0 ; y < height ; y++)
5917     {
5918       yp = height - (y+1) ;
5919 
5920 #if 0
5921       if (mri->type == MRI_UCHAR)
5922         image_to_buffer(I->image, mri, slice) ;
5923       else
5924 #endif
5925         switch (mri->type)
5926           {
5927           case MRI_INT:
5928             memcpy
5929               (IMAGEIpix(I, 0, yp),mri->slices[slice][y],width*sizeof(int)) ;
5930             break ;
5931           case MRI_FLOAT:
5932             memcpy
5933               (IMAGEFpix(I, 0, yp),mri->slices[slice][y],width*sizeof(float));
5934             break ;
5935           case MRI_UCHAR:
5936             memcpy(IMAGEpix(I, 0, yp), mri->slices[slice][y],
5937                    width*sizeof(unsigned char)) ;
5938             break ;
5939           default:
5940           case MRI_LONG:
5941             ImageFree(&I) ;
5942             ErrorReturn
5943               (NULL,
5944                (ERROR_UNSUPPORTED,
5945                 "MRItoImage: unsupported type %d",
5946                 mri->type)) ;
5947             break ;
5948           }
5949     }
5950 
5951   return(I) ;
5952 }
5953 
5954 MRI *
5955 ImageToMRI(IMAGE *I)
5956 {
5957   MRI *mri;
5958   int  width, height, depth, type, nframes, y, yp, x ;
5959   int frames;
5960 
5961   type = MRI_UCHAR; // to make compiler happy
5962   width = I->ocols;
5963   height = I->orows;
5964   depth = 1;
5965   nframes = I->num_frame;
5966 
5967   switch(I->pixel_format)
5968     {
5969     case PFBYTE:
5970       type = MRI_UCHAR;
5971       break;
5972     case PFSHORT:
5973       type = MRI_SHORT;
5974       break;
5975     case PFINT:
5976       type = MRI_INT;
5977       break;
5978     case PFFLOAT:
5979       type = MRI_FLOAT;
5980       break;
5981     case PFDOUBLE:
5982     case PFCOMPLEX:
5983     default:
5984       ErrorExit
5985         (ERROR_BADPARM, "IMAGE type = %d not supported\n", I->pixel_format);
5986       break;
5987     }
5988   // allocate memory
5989   if (nframes <= 1)
5990     mri = MRIalloc(width, height, depth, type);
5991   else
5992     mri = MRIallocSequence(width, height, depth, type, nframes);
5993 
5994   // just fake the size
5995   mri->nframes = nframes;
5996   mri->imnr0 = 1;
5997   mri->imnr1 = 1;
5998   mri->thick = mri->ps = 1.0;
5999   mri->xsize = mri->ysize = mri->zsize = 1.0;
6000   mri->xend = mri->width  * mri->xsize / 2.0;
6001   mri->xstart = -mri->xend;
6002   mri->yend = mri->height * mri->ysize / 2.0;
6003   mri->ystart = -mri->yend;
6004   mri->zend = mri->depth  * mri->zsize / 2.0;
6005   mri->zstart = -mri->zend;
6006   mri->fov = ((mri->xend - mri->xstart) > (mri->yend - mri->ystart) ?
6007               (mri->xend - mri->xstart) : (mri->yend - mri->ystart));
6008   // set orientation to be coronal
6009   mri->x_r = -1; mri->y_r =  0; mri->z_r =  0; mri->c_r = 0;
6010   mri->x_a =  0; mri->y_a =  0; mri->z_a =  1; mri->c_a = 0;
6011   mri->x_s =  0; mri->y_s = -1; mri->z_s =  0; mri->c_s = 0;
6012 
6013   // hips coordinate system is inverted
6014   for (frames = 0; frames < nframes; ++frames)
6015     {
6016 
6017       for (y = 0 ; y < height ; y++)
6018         {
6019           yp = height - (y+1) ;
6020 
6021           for (x = 0; x < width; ++x)
6022             {
6023               switch (mri->type)
6024                 {
6025                 case MRI_UCHAR:
6026                   MRIseq_vox(mri, x, y, 0, frames) = *IMAGEpix(I, x, yp);
6027                   break ;
6028                 case MRI_SHORT:
6029                   MRISseq_vox(mri, x, y, 0, frames) = *IMAGESpix(I, x, yp);
6030                   break;
6031                 case MRI_INT:
6032                   MRIIseq_vox(mri, x, y, 0, frames) = *IMAGEIpix(I, x, yp);
6033                   break ;
6034                 case MRI_FLOAT:
6035                   MRIFseq_vox(mri, x, y, 0, frames) = *IMAGEFpix(I, x, yp);
6036                   break ;
6037                 default:
6038                   ErrorReturn
6039                     (NULL,
6040                      (ERROR_UNSUPPORTED,
6041                       "MRItoImage: unsupported type %d",
6042                       mri->type)) ;
6043                   break ;
6044                 }
6045             }
6046         }
6047     } // frames
6048   return(mri) ;
6049 }
6050 
6051 /*-----------------------------------------------------
6052   Parameters:
6053 
6054   Returns value:
6055 
6056   Description
6057   Build an MRI from all values s.t. min_val <= val <= max_val
6058   ------------------------------------------------------*/
6059 MRI *
6060 MRIextractValues(MRI *mri_src, MRI *mri_dst, float min_val, float max_val)
6061 {
6062   BUFTYPE  *psrc, *pdst, val ;
6063   float    *pfsrc, *pfdst, fval ;
6064   int      frame, x, y, z, width, height, depth ;
6065 
6066   width = mri_src->width ;
6067   height = mri_src->height ;
6068   depth = mri_src->depth ;
6069   if (!mri_dst)
6070     mri_dst = MRIclone(mri_src, NULL) ;
6071 
6072   for (frame = 0 ; frame < mri_src->nframes ; frame++)
6073     {
6074       for (z = 0 ; z < depth ; z++)
6075         {
6076           for (y = 0 ; y < height ; y++)
6077             {
6078               switch (mri_src->type)
6079                 {
6080                 case MRI_UCHAR:
6081                   psrc = &MRIseq_vox(mri_src, 0, y, z, frame) ;
6082                   pdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
6083                   for (x = 0 ; x < width ; x++)
6084                     {
6085                       val = *psrc++ ;
6086                       if ((val < min_val) || (val > max_val))
6087                         val = 0 ;
6088                       *pdst++ = val ;
6089                     }
6090                   break ;
6091                 case MRI_FLOAT:
6092                   pfsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
6093                   pfdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
6094                   for (x = 0 ; x < width ; x++)
6095                     {
6096                       fval = *pfsrc++ ;
6097                       if ((fval < min_val) || (fval > max_val))
6098                         fval = 0.0f ;
6099                       *pfdst++ = fval ;
6100                     }
6101                   break ;
6102                 default:
6103                   ErrorReturn
6104                     (NULL,
6105                      (ERROR_UNSUPPORTED,
6106                       "MRIextractValues: unsupported type %d",mri_src->type));
6107                 }
6108             }
6109         }
6110     }
6111 
6112   return(mri_dst) ;
6113 }
6114 /*-----------------------------------------------------
6115   Parameters:
6116 
6117   Returns value:
6118 
6119   Description
6120   ------------------------------------------------------*/
6121 MRI *
6122 MRIupsample2(MRI *mri_src, MRI *mri_dst)
6123 {
6124   int     width, depth, height, x, y, z ;
6125   BUFTYPE *pdst ;
6126   short   *psdst ;
6127   float   *pfdst ;
6128 
6129   if (mri_dst && mri_src->type != mri_dst->type)
6130     ErrorReturn
6131       (NULL,
6132        (ERROR_UNSUPPORTED, "MRIupsample2: source and dst must be same type"));
6133 
6134   width = 2*mri_src->width ;
6135   height = 2*mri_src->height ;
6136   depth = 2*mri_src->depth ;
6137 
6138   if (!mri_dst)
6139     {
6140       mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
6141       MRIcopyHeader(mri_src, mri_dst) ;
6142     }
6143 
6144   for (z = 0 ; z < depth ; z++)
6145     {
6146       for (y = 0 ; y < height ; y++)
6147         {
6148           switch (mri_src->type)
6149             {
6150             case MRI_UCHAR:
6151               pdst = &MRIvox(mri_dst, 0, y, z) ;
6152               for (x = 0 ; x < width ; x++)
6153                 *pdst++ = MRIvox(mri_src, x/2, y/2, z/2) ;
6154               break ;
6155             case MRI_SHORT:
6156               psdst = &MRISvox(mri_dst, 0, y, z) ;
6157               for (x = 0 ; x < width ; x++)
6158                 *psdst++ = MRISvox(mri_src, x/2, y/2, z/2) ;
6159               break ;
6160             case MRI_FLOAT:
6161               pfdst = &MRIFvox(mri_dst, 0, y, z) ;
6162               for (x = 0 ; x < width ; x++)
6163                 *pfdst++ = MRIFvox(mri_src, x/2, y/2, z/2) ;
6164               break ;
6165             default:
6166               ErrorReturn
6167                 (NULL,
6168                  (ERROR_UNSUPPORTED,
6169                   "MRIupsample2: unsupported src type %d", mri_src->type)) ;
6170             }
6171 
6172         }
6173     }
6174 
6175   mri_dst->imnr0 = mri_src->imnr0 ;
6176   mri_dst->imnr1 = mri_src->imnr0 + mri_dst->depth - 1 ;
6177 
6178   mri_dst->xsize = mri_src->xsize/2 ;
6179   mri_dst->ysize = mri_src->ysize/2 ;
6180   mri_dst->zsize = mri_src->zsize/2 ;
6181 
6182   mri_dst->ras_good_flag = 0;
6183 
6184   return(mri_dst) ;
6185 }
6186 MRI *
6187 MRIdownsample2LabeledVolume(MRI *mri_src, MRI *mri_dst)
6188 {
6189   int     width, depth, height, x, y, z, x1, y1, z1, counts[256], label,
6190     max_count, out_label ;
6191   BUFTYPE *psrc ;
6192 
6193   if (mri_src->type != MRI_UCHAR)
6194     ErrorReturn(NULL,
6195                 (ERROR_UNSUPPORTED,
6196                  "MRIdownsample2LabeledVolume: source must be UCHAR"));
6197 
6198   width = mri_src->width/2 ;
6199   height = mri_src->height/2 ;
6200   depth = mri_src->depth/2 ;
6201 
6202   if (!mri_dst)
6203     {
6204       mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
6205       MRIcopyHeader(mri_src, mri_dst) ;
6206     }
6207 
6208   MRIclear(mri_dst) ;
6209   for (z = 0 ; z < depth ; z++)
6210     {
6211       for (y = 0 ; y < height ; y++)
6212         {
6213           for (x = 0 ; x < width ; x++)
6214             {
6215               memset(counts, 0, sizeof(counts)) ;
6216               if (x == 96 && y == 66 && z == 56)
6217                 DiagBreak() ;
6218               for (z1 = 2*z ; z1 <= 2*z+1 ; z1++)
6219                 {
6220                   for (y1 = 2*y ; y1 <= 2*y+1 ; y1++)
6221                     {
6222                       psrc = &MRIvox(mri_src, 2*x, y1, z1) ;
6223                       for (x1 = 2*x ; x1 <= 2*x+1 ; x1++)
6224                         {
6225                           label = *psrc++ ;
6226                           counts[label]++ ;
6227                         }
6228                     }
6229                 }
6230               for (out_label = label = 0, max_count = counts[0] ;
6231                    label <= 255 ;
6232                    label++)
6233                 {
6234                   if (counts[label] > max_count)
6235                     {
6236                       out_label = label ;
6237                       max_count = counts[label] ;
6238                     }
6239                 }
6240               MRIvox(mri_dst, x, y, z) = out_label ;
6241             }
6242         }
6243     }
6244 
6245   mri_dst->imnr0 = mri_src->imnr0 ;
6246   mri_dst->imnr1 = mri_src->imnr0 + mri_dst->depth - 1 ;
6247   mri_dst->xsize = mri_src->xsize*2 ;
6248   mri_dst->ysize = mri_src->ysize*2 ;
6249   mri_dst->zsize = mri_src->zsize*2 ;
6250 
6251   mri_dst->ras_good_flag = 0;
6252 
6253   return(mri_dst) ;
6254 }
6255 /*-----------------------------------------------------
6256   Parameters:
6257 
6258   Returns value:
6259 
6260   Description
6261   ------------------------------------------------------*/
6262 MRI *
6263 MRIdownsample2(MRI *mri_src, MRI *mri_dst)
6264 {
6265   int     width, depth, height, x, y, z, x1, y1, z1 ;
6266   BUFTYPE *psrc ;
6267   short   *pssrc ;
6268   float   val ;
6269 
6270   if (mri_dst && mri_src->type != mri_dst->type)
6271     ErrorReturn
6272       (NULL,
6273        (ERROR_UNSUPPORTED,
6274         "MRIdownsample2: source and dst must be same type"));
6275 
6276   width = mri_src->width/2 ;
6277   height = mri_src->height/2 ;
6278   depth = mri_src->depth/2 ;
6279 
6280   if (!mri_dst)
6281     {
6282       mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
6283       MRIcopyHeader(mri_src, mri_dst) ;
6284     }
6285 
6286   MRIclear(mri_dst) ;
6287   for (z = 0 ; z < depth ; z++)
6288     {
6289       for (y = 0 ; y < height ; y++)
6290         {
6291           for (x = 0 ; x < width ; x++)
6292             {
6293               for (val = 0.0f, z1 = 2*z ; z1 <= 2*z+1 ; z1++)
6294                 {
6295                   for (y1 = 2*y ; y1 <= 2*y+1 ; y1++)
6296                     {
6297                       switch (mri_src->type)
6298                         {
6299                         case MRI_UCHAR:
6300                           psrc = &MRIvox(mri_src, 2*x, y1, z1) ;
6301                           for (x1 = 2*x ; x1 <= 2*x+1 ; x1++)
6302                             val += *psrc++ ;
6303                           break ;
6304                         case MRI_SHORT:
6305                           pssrc = &MRISvox(mri_src, 2*x, y1, z1) ;
6306                           for (x1 = 2*x ; x1 <= 2*x+1 ; x1++)
6307                             val += *pssrc++ ;
6308                           break ;
6309                         default:
6310                           ErrorReturn
6311                             (NULL,
6312                              (ERROR_UNSUPPORTED,
6313                               "MRIdownsample2: unsupported input type %d",
6314                               mri_src->type));
6315                         }
6316                     }
6317                 }
6318               switch (mri_src->type)
6319                 {
6320                 case MRI_UCHAR:
6321                   MRIvox(mri_dst, x, y, z) = (BUFTYPE)nint(val/8.0f) ;
6322                   break ;
6323                 case MRI_SHORT:
6324                   MRISvox(mri_dst, x, y, z) = (short)nint(val/8.0f) ;
6325                   break ;
6326                 }
6327             }
6328         }
6329     }
6330 
6331   mri_dst->imnr0 = mri_src->imnr0 ;
6332   mri_dst->imnr1 = mri_src->imnr0 + mri_dst->depth - 1 ;
6333   mri_dst->xsize = mri_src->xsize*2 ;
6334   mri_dst->ysize = mri_src->ysize*2 ;
6335   mri_dst->zsize = mri_src->zsize*2 ;
6336 
6337   mri_dst->ras_good_flag = 0;
6338 
6339   return(mri_dst) ;
6340 }
6341 /*-------------------------------------------------------------
6342   MRI MRIvalueFill(MRI *mri, float value) -- fills an mri volume
6343   with the given value. Type of mri can be anything.
6344   -------------------------------------------------------------*/
6345 int MRIvalueFill(MRI *mri, float value)
6346 {
6347   int c,r,s,f;
6348 
6349   for(c=0; c < mri->width; c++){
6350     for(r=0; r < mri->height; r++){
6351       for(s=0; s < mri->depth; s++){
6352         for(f=0; f < mri->nframes; f++){
6353           switch(mri->type){
6354           case MRI_UCHAR:
6355             MRIseq_vox(mri,c,r,s,f) = (unsigned char) (nint(value));
6356             break;
6357           case MRI_SHORT:
6358             MRISseq_vox(mri,c,r,s,f) = (short) (nint(value));
6359             break;
6360           case MRI_INT:
6361             MRIIseq_vox(mri,c,r,s,f) = (int) (nint(value));
6362             break;
6363           case MRI_FLOAT:
6364             MRIFseq_vox(mri,c,r,s,f) = value;
6365             break;
6366           }
6367         }
6368       }
6369     }
6370   }
6371 
6372   return(0);
6373 }
6374 /*-----------------------------------------------------
6375   Parameters:
6376 
6377   Returns value:
6378 
6379   Description
6380   Iteratively set all voxels in mri_dst that neighbor
6381   a voxel that has already been filled (starting with the seed),
6382   and for which the corresponding voxel in mri_src is
6383   below threshold.
6384   ------------------------------------------------------*/
6385 MRI *
6386 MRIfill(MRI *mri_src, MRI *mri_dst, int seed_x, int seed_y,
6387         int seed_z, int threshold, int fill_val, int max_count)
6388 {
6389   int     width, height, depth, x, y, z, nfilled, xmin, xmax, ymin, ymax,
6390     zmin, zmax, on, x0, x1, y0, y1, z0, z1 ;
6391   BUFTYPE *psrc, *pdst, val ;
6392 
6393   width = mri_src->width ;
6394   height = mri_src->height ;
6395   depth = mri_src->depth ;
6396   if (!mri_dst)
6397     mri_dst = MRIclone(mri_src, NULL) ;
6398 
6399   if (seed_x < 0)
6400     seed_x = 0 ;
6401   else if (seed_x >= width)
6402     seed_x = width-1 ;
6403   if (seed_y < 0)
6404     seed_y = 0 ;
6405   else if (seed_y >= height)
6406     seed_y = height-1 ;
6407   if (seed_z < 0)
6408     seed_z = 0 ;
6409   else if (seed_z >= depth)
6410     seed_z = depth-1 ;
6411 
6412   xmin = MAX(seed_x-1,0) ; xmax = MIN(seed_x+1, width-1) ;
6413   ymin = MAX(seed_y-1,0) ; ymax = MIN(seed_y+1, height-1) ;
6414   zmin = MAX(seed_z-1,0) ; zmax = MIN(seed_z+1, depth-1) ;
6415 
6416   /* replace all occurrences of fill_val with fill_val-1 */
6417   for (z = 0 ; z < depth ; z++)
6418     {
6419       for (y = 0 ; y < height ; y++)
6420         {
6421           pdst = &MRIvox(mri_dst, 0, y, z) ;
6422           for (x = 0 ; x < width ; x++, pdst++)
6423             {
6424               val = *pdst ;
6425               if (val == fill_val)
6426                 *pdst = val-1 ;
6427             }
6428         }
6429     }
6430 
6431   MRIvox(mri_dst, seed_x, seed_y, seed_z) = fill_val ;
6432   do
6433     {
6434       z0 = zmin ; z1 = zmax ; y0 = ymin ; y1 = ymax ; x0 = xmin ; x1 = xmax ;
6435       nfilled = 0 ;
6436       for (z = zmin ; z <= zmax ; z++)
6437         {
6438           for (y = ymin ; y <= ymax ; y++)
6439             {
6440               psrc = &MRIvox(mri_src, xmin, y, z) ;
6441               pdst = &MRIvox(mri_dst, xmin, y, z) ;
6442               for (x = xmin ; x <= xmax ; x++, psrc++, pdst++)
6443                 {
6444                   val = *psrc ;
6445                   if ((val > threshold) || (*pdst == fill_val))
6446                     continue ;
6447 
6448                   on = 0 ;
6449                   if (x > 0)
6450                     on = (MRIvox(mri_dst, x-1, y, z) == fill_val) ;
6451                   if (!on && (x < width-1))
6452                     on = (MRIvox(mri_dst, x+1, y, z) == fill_val) ;
6453                   if (!on && (y > 0))
6454                     on = (MRIvox(mri_dst, x, y-1, z) == fill_val) ;
6455                   if (!on && (y < height-1))
6456                     on = (MRIvox(mri_dst, x, y+1, z) == fill_val) ;
6457                   if (!on && (z > 0))
6458                     on = (MRIvox(mri_dst, x, y, z-1) == fill_val) ;
6459                   if (!on && (z < depth-1))
6460                     on = (MRIvox(mri_dst, x, y, z+1) == fill_val) ;
6461                   if (on)
6462                     {
6463                       if (x <= x0)
6464                         x0 = MAX(x-1,0) ;
6465                       if (x >= x1)
6466                         x1 = MIN(x+1,width-1) ;
6467                       if (y <= y0)
6468                         y0 = MAX(y-1,0) ;
6469                       if (y >= y1)
6470                         y1 = MIN(y+1,height-1) ;
6471                       if (z <= z0)
6472                         z0 = MAX(z-1,0) ;
6473                       if (z >= z1)
6474                         z1 = MIN(z+1,depth-1) ;
6475                       nfilled++ ;
6476                       *pdst = fill_val ;
6477                     }
6478                 }
6479             }
6480         }
6481       zmin = z0 ; zmax = z1 ; ymin = y0 ; ymax = y1 ; xmin = x0 ; xmax = x1 ;
6482       /*    fprintf(stderr, "# filled = %d\n", nfilled) ;*/
6483       if ((max_count > 0) && (nfilled > max_count))
6484         break ;
6485     } while (nfilled > 0) ;
6486 
6487   return(mri_dst) ;
6488 }
6489 /*-----------------------------------------------------
6490   Parameters:
6491 
6492   Returns value:
6493 
6494   Description
6495   ------------------------------------------------------*/
6496 MRI *
6497 MRIfillFG(MRI *mri_src, MRI *mri_dst, int seed_x, int seed_y,
6498           int seed_z, int threshold, int fill_val, int *npix)
6499 {
6500   int     width, height, depth, x, y, z, nfilled, xmin, xmax, ymin, ymax,
6501     zmin, zmax, on, x0, x1, y0, y1, z0, z1, total_pix ;
6502   BUFTYPE *psrc, *pdst, val ;
6503 
6504   width = mri_src->width ;
6505   height = mri_src->height ;
6506   depth = mri_src->depth ;
6507   if (!mri_dst)
6508     mri_dst = MRIclone(mri_src, NULL) ;
6509 
6510   if (seed_x < 0)
6511     seed_x = 0 ;
6512   else if (seed_x >= width)
6513     seed_x = width-1 ;
6514   if (seed_y < 0)
6515     seed_y = 0 ;
6516   else if (seed_y >= height)
6517     seed_y = width-1 ;
6518   if (seed_z < 0)
6519     seed_z = 0 ;
6520   else if (seed_z >= depth)
6521     seed_z = width-1 ;
6522 
6523   xmin = MAX(seed_x-1,0) ; xmax = MIN(seed_x+1, width-1) ;
6524   ymin = MAX(seed_y-1,0) ; ymax = MIN(seed_y+1, height-1) ;
6525   zmin = MAX(seed_z-1,0) ; zmax = MIN(seed_z+1, depth-1) ;
6526 
6527   /* replace all occurrences of fill_val with fill_val-1 */
6528   for (z = 0 ; z < depth ; z++)
6529     {
6530       for (y = 0 ; y < height ; y++)
6531         {
6532           pdst = &MRIvox(mri_dst, 0, y, z) ;
6533           for (x = 0 ; x < width ; x++, pdst++)
6534             {
6535               val = *pdst ;
6536               if (val == fill_val)
6537                 *pdst = val-1 ;
6538             }
6539         }
6540     }
6541 
6542   MRIvox(mri_dst, seed_x, seed_y, seed_z) = fill_val ;
6543   total_pix = 1 ;  /* include the seed point */
6544   do
6545     {
6546       z0 = zmin ; z1 = zmax ; y0 = ymin ; y1 = ymax ; x0 = xmin ; x1 = xmax ;
6547       nfilled = 0 ;
6548       for (z = zmin ; z <= zmax ; z++)
6549         {
6550           for (y = ymin ; y <= ymax ; y++)
6551             {
6552               psrc = &MRIvox(mri_src, xmin, y, z) ;
6553               pdst = &MRIvox(mri_dst, xmin, y, z) ;
6554               for (x = xmin ; x <= xmax ; x++, psrc++, pdst++)
6555                 {
6556                   val = *psrc ;
6557                   if ((val < threshold) || (*pdst == fill_val))
6558                     continue ;
6559 
6560                   on = 0 ;
6561                   if (x > 0)
6562                     on = (MRIvox(mri_dst, x-1, y, z) == fill_val) ;
6563                   if (!on && (x < width-1))
6564                     on = (MRIvox(mri_dst, x+1, y, z) == fill_val) ;
6565                   if (!on && (y > 0))
6566                     on = (MRIvox(mri_dst, x, y-1, z) == fill_val) ;
6567                   if (!on && (y < height-1))
6568                     on = (MRIvox(mri_dst, x, y+1, z) == fill_val) ;
6569                   if (!on && (z > 0))
6570                     on = (MRIvox(mri_dst, x, y, z-1) == fill_val) ;
6571                   if (!on && (z < depth-1))
6572                     on = (MRIvox(mri_dst, x, y, z+1) == fill_val) ;
6573                   if (on)
6574                     {
6575                       if (x <= x0)
6576                         x0 = MAX(x-1,0) ;
6577                       if (x >= x1)
6578                         x1 = MIN(x+1,width-1) ;
6579                       if (y <= y0)
6580                         y0 = MAX(y-1,0) ;
6581                       if (y >= y1)
6582                         y1 = MIN(y+1,height-1) ;
6583                       if (z <= z0)
6584                         z0 = MAX(z-1,0) ;
6585                       if (z >= z1)
6586                         z1 = MIN(z+1,depth-1) ;
6587                       nfilled++ ;
6588                       *pdst = fill_val ;
6589                     }
6590                 }
6591             }
6592         }
6593       zmin = z0 ; zmax = z1 ; ymin = y0 ; ymax = y1 ; xmin = x0 ; xmax = x1 ;
6594       total_pix += nfilled ;
6595       /*    fprintf(stderr, "# filled = %d\n", nfilled) ;*/
6596     } while (nfilled > 0) ;
6597 
6598   if (npix)
6599     *npix = total_pix ;
6600   return(mri_dst) ;
6601 }
6602 /*-----------------------------------------------------
6603   Parameters:
6604 
6605   Returns value:
6606 
6607   Description
6608   ------------------------------------------------------*/
6609 MRI *
6610 MRIfillBG(MRI *mri_src, MRI *mri_dst, int seed_x, int seed_y,
6611           int seed_z, int threshold, int fill_val, int *npix)
6612 {
6613   int     width, height, depth, x, y, z, nfilled, xmin, xmax, ymin, ymax,
6614     zmin, zmax, on, x0, x1, y0, y1, z0, z1, total_pix ;
6615   BUFTYPE *psrc, *pdst, val ;
6616 
6617   width = mri_src->width ;
6618   height = mri_src->height ;
6619   depth = mri_src->depth ;
6620   if (!mri_dst)
6621     mri_dst = MRIclone(mri_src, NULL) ;
6622 
6623   if (seed_x < 0)
6624     seed_x = 0 ;
6625   else if (seed_x >= width)
6626     seed_x = width-1 ;
6627   if (seed_y < 0)
6628     seed_y = 0 ;
6629   else if (seed_y >= height)
6630     seed_y = width-1 ;
6631   if (seed_z < 0)
6632     seed_z = 0 ;
6633   else if (seed_z >= depth)
6634     seed_z = width-1 ;
6635 
6636   xmin = MAX(seed_x-1,0) ; xmax = MIN(seed_x+1, width-1) ;
6637   ymin = MAX(seed_y-1,0) ; ymax = MIN(seed_y+1, height-1) ;
6638   zmin = MAX(seed_z-1,0) ; zmax = MIN(seed_z+1, depth-1) ;
6639 
6640   /* replace all occurrences of fill_val with fill_val-1 */
6641   for (z = 0 ; z < depth ; z++)
6642     {
6643       for (y = 0 ; y < height ; y++)
6644         {
6645           pdst = &MRIvox(mri_dst, 0, y, z) ;
6646           for (x = 0 ; x < width ; x++, pdst++)
6647             {
6648               val = *pdst ;
6649               if (val == fill_val)
6650                 *pdst = val-1 ;
6651             }
6652         }
6653     }
6654 
6655   MRIvox(mri_dst, seed_x, seed_y, seed_z) = fill_val ;
6656   total_pix = 0 ;
6657   do
6658     {
6659       z0 = zmin ; z1 = zmax ; y0 = ymin ; y1 = ymax ; x0 = xmin ; x1 = xmax ;
6660       nfilled = 0 ;
6661       for (z = zmin ; z <= zmax ; z++)
6662         {
6663           for (y = ymin ; y <= ymax ; y++)
6664             {
6665               psrc = &MRIvox(mri_src, xmin, y, z) ;
6666               pdst = &MRIvox(mri_dst, xmin, y, z) ;
6667               for (x = xmin ; x <= xmax ; x++, psrc++, pdst++)
6668                 {
6669                   if (z == 130 && (y == 145 || y == 146) && x == 142)
6670                     DiagBreak() ;
6671                   val = *psrc ;
6672                   if ((val > threshold) || (*pdst == fill_val))
6673                     continue ;
6674 
6675                   on = 0 ;
6676                   if (x > 0)
6677                     on = (MRIvox(mri_dst, x-1, y, z) == fill_val) ;
6678                   if (!on && (x < width-1))
6679                     on = (MRIvox(mri_dst, x+1, y, z) == fill_val) ;
6680                   if (!on && (y > 0))
6681                     on = (MRIvox(mri_dst, x, y-1, z) == fill_val) ;
6682                   if (!on && (y < height-1))
6683                     on = (MRIvox(mri_dst, x, y+1, z) == fill_val) ;
6684                   if (!on && (z > 0))
6685                     on = (MRIvox(mri_dst, x, y, z-1) == fill_val) ;
6686                   if (!on && (z < depth-1))
6687                     on = (MRIvox(mri_dst, x, y, z+1) == fill_val) ;
6688                   if (on)
6689                     {
6690                       if (z == 130 && (y == 145 || y == 146) && x == 142)
6691                         DiagBreak() ;
6692                       if (x <= x0)
6693                         x0 = MAX(x-1,0) ;
6694                       if (x >= x1)
6695                         x1 = MIN(x+1,width-1) ;
6696                       if (y <= y0)
6697                         y0 = MAX(y-1,0) ;
6698                       if (y >= y1)
6699                         y1 = MIN(y+1,height-1) ;
6700                       if (z <= z0)
6701                         z0 = MAX(z-1,0) ;
6702                       if (z >= z1)
6703                         z1 = MIN(z+1,depth-1) ;
6704                       nfilled++ ;
6705                       *pdst = fill_val ;
6706                     }
6707                 }
6708             }
6709         }
6710       zmin = z0 ; zmax = z1 ; ymin = y0 ; ymax = y1 ; xmin = x0 ; xmax = x1 ;
6711       total_pix += nfilled ;
6712       /*    fprintf(stderr, "# filled = %d\n", nfilled) ;*/
6713     } while (nfilled > 0) ;
6714 
6715   if (npix)
6716     *npix = total_pix ;
6717   return(mri_dst) ;
6718 }
6719 /*-----------------------------------------------------
6720   Parameters:
6721 
6722   Returns value:
6723 
6724   Description
6725   ------------------------------------------------------*/
6726 int
6727 MRIsetResolution(MRI *mri, float xres, float yres, float zres)
6728 {
6729   mri->ps = (xres+yres+zres) / 3.0f ;
6730   mri->xsize = xres ;
6731   mri->ysize = yres ;
6732   mri->zsize = zres ;
6733   mri->xstart *= xres ; mri->xend *= xres ;
6734   mri->ystart *= yres ; mri->yend *= yres ;
6735   mri->zstart *= zres ; mri->zend *= zres ;
6736   mri->thick = MAX(MAX(xres,yres),zres) ;
6737 #if 0
6738   mri->x_r = mri->x_r * xres ;
6739   mri->x_a = mri->x_a * xres ;
6740   mri->x_s = mri->x_s * xres ;
6741   mri->y_r = mri->y_r * yres ;
6742   mri->y_a = mri->y_a * yres ;
6743   mri->y_s = mri->y_s * yres ;
6744   mri->z_r = mri->z_r * zres ;
6745   mri->z_a = mri->z_a * zres ;
6746   mri->z_s = mri->z_s * zres ;
6747 #endif
6748   return(NO_ERROR) ;
6749 }
6750 /*-----------------------------------------------------
6751   Parameters:
6752 
6753   Returns value:
6754 
6755   Description
6756   ------------------------------------------------------*/
6757 int
6758 MRIsetTransform(MRI *mri,   General_transform *transform)
6759 {
6760   mri->transform = *transform ;
6761   mri->linear_transform = get_linear_transform_ptr(transform) ;
6762   mri->inverse_linear_transform = get_inverse_linear_transform_ptr(transform) ;
6763 
6764   return(NO_ERROR) ;
6765 }
6766 /*-----------------------------------------------------
6767   Parameters:
6768 
6769   Returns value:
6770 
6771   Description
6772   ------------------------------------------------------*/
6773 MRI *
6774 MRIextractTalairachPlane(MRI *mri_src, MRI *mri_dst, int orientation,
6775                          int x, int y, int z, int wsize)
6776 {
6777   Real     e1_x, e1_y, e1_z, e2_x, e2_y, e2_z, xbase, ybase, zbase ;
6778   int      whalf, xk, yk, xi, yi, zi ;
6779   Real     ex, ey, ez, len, x0, y0, z0 ;
6780 
6781   whalf = (wsize-1)/2 ;
6782 
6783   if (!mri_dst)
6784     {
6785       mri_dst = MRIalloc(wsize, wsize, 1, MRI_UCHAR) ;
6786       MRIcopyHeader(mri_src, mri_dst) ;
6787       mri_dst->xstart = x-whalf*mri_dst->xsize ;
6788       mri_dst->ystart = y-whalf*mri_dst->ysize ;
6789       mri_dst->zstart = z-whalf*mri_dst->zsize ;
6790       mri_dst->xend = mri_dst->xstart + wsize*mri_dst->xsize ;
6791       mri_dst->yend = mri_dst->ystart + wsize*mri_dst->ysize ;
6792       mri_dst->zend = mri_dst->zstart + wsize*mri_dst->zsize ;
6793       mri_dst->imnr0 = z + mri_src->imnr0 ;
6794       mri_dst->imnr1 = mri_dst->imnr0 ;
6795     }
6796 
6797   MRIvoxelToTalairachVoxel(mri_src, x, y, z, &x0, &y0, &z0) ;
6798   switch (orientation)
6799     {
6800     default:
6801     case MRI_CORONAL:   /* basis vectors in x-y plane */
6802       /* the 'x' basis vector */
6803       ex = (Real)x0+1 ; ey = (Real)y0 ; ez = (Real)z0 ;
6804       MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6805       e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6806 
6807       /* the 'y' basis vector */
6808       ex = (Real)x0 ; ey = (Real)y0+1 ; ez = (Real)z0 ;
6809       MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6810       e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6811       break ;
6812     case MRI_HORIZONTAL:  /* basis vectors in x-z plane */
6813       /* the 'x' basis vector */
6814       ex = (Real)x0+1 ; ey = (Real)y0 ; ez = (Real)z0 ;
6815       MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6816       e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6817 
6818       /* the 'y' basis vector */
6819       ex = (Real)x0 ; ey = (Real)y0 ; ez = (Real)z0+1 ;
6820       MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6821       e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6822       break ;
6823     case MRI_SAGITTAL:    /* basis vectors in y-z plane */
6824       /* the 'x' basis vector */
6825       ex = (Real)x0 ; ey = (Real)y0 ; ez = (Real)z0+1.0 ;
6826       MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6827       e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6828 
6829       /* the 'y' basis vector */
6830       ex = (Real)x0 ; ey = (Real)y0+1.0 ; ez = (Real)z0 ;
6831       MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6832       e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6833       break ;
6834     }
6835 
6836   len = sqrt(e1_x*e1_x + e1_y*e1_y + e1_z*e1_z) ;
6837   /*  e1_x /= len ; e1_y /= len ; e1_z /= len ;*/
6838   len = sqrt(e2_x*e2_x + e2_y*e2_y + e2_z*e2_z) ;
6839   /*  e2_x /= len ; e2_y /= len ; e2_z /= len ;*/
6840 
6841   for (yk = -whalf ; yk <= whalf ; yk++)
6842     {
6843       xbase = (float)x + (float)yk * e2_x ;
6844       ybase = (float)y + (float)yk * e2_y ;
6845       zbase = (float)z + (float)yk * e2_z ;
6846       for (xk = -whalf ; xk <= whalf ; xk++)
6847         {
6848           /* in-plane vect. is linear combination of scaled basis vects */
6849           xi = mri_src->xi[nint(xbase + xk*e1_x)] ;
6850           yi = mri_src->yi[nint(ybase + xk*e1_y)] ;
6851           zi = mri_src->zi[nint(zbase + xk*e1_z)] ;
6852           MRIvox(mri_dst, xk+whalf,yk+whalf,0) = MRIvox(mri_src, xi, yi, zi) ;
6853         }
6854     }
6855 
6856   return(mri_dst) ;
6857 }
6858 /*-----------------------------------------------------
6859   Parameters:
6860 
6861   Returns value:
6862 
6863   Description
6864   ------------------------------------------------------*/
6865 MRI *
6866 MRIextractArbitraryPlane(MRI *mri_src, MRI *mri_dst,
6867                          Real e1_x, Real e1_y, Real e1_z,
6868                          Real e2_x, Real e2_y, Real e2_z,
6869                          int x, int y, int z, int wsize)
6870 {
6871   Real     xbase, ybase, zbase ;
6872   int      whalf, xk, yk, xi, yi, zi ;
6873 
6874   whalf = (wsize-1)/2 ;
6875 
6876   if (!mri_dst)
6877     {
6878       mri_dst = MRIalloc(wsize, wsize, 1, MRI_UCHAR) ;
6879       MRIcopyHeader(mri_src, mri_dst) ;
6880       mri_dst->xstart = x-whalf*mri_dst->xsize ;
6881       mri_dst->ystart = y-whalf*mri_dst->ysize ;
6882       mri_dst->zstart = z-whalf*mri_dst->zsize ;
6883       mri_dst->xend = mri_dst->xstart + wsize*mri_dst->xsize ;
6884       mri_dst->yend = mri_dst->ystart + wsize*mri_dst->ysize ;
6885       mri_dst->zend = mri_dst->zstart + wsize*mri_dst->zsize ;
6886       mri_dst->imnr0 = z + mri_src->imnr0 ;
6887       mri_dst->imnr1 = mri_dst->imnr0 ;
6888     }
6889 
6890 
6891 
6892   for (yk = -whalf ; yk <= whalf ; yk++)
6893     {
6894       xbase = (float)x + (float)yk * e2_x ;
6895       ybase = (float)y + (float)yk * e2_y ;
6896       zbase = (float)z + (float)yk * e2_z ;
6897       for (xk = -whalf ; xk <= whalf ; xk++)
6898         {
6899           /* in-plane vect. is linear combination of scaled basis vects */
6900           xi = mri_src->xi[nint(xbase + xk*e1_x)] ;
6901           yi = mri_src->yi[nint(ybase + xk*e1_y)] ;
6902           zi = mri_src->zi[nint(zbase + xk*e1_z)] ;
6903           MRIvox(mri_dst, xk+whalf,yk+whalf,0) = MRIvox(mri_src, xi, yi, zi) ;
6904         }
6905     }
6906 
6907   return(mri_dst) ;
6908 }
6909 /*-----------------------------------------------------
6910   Parameters:
6911 
6912   Returns value:
6913 
6914   Description
6915   ------------------------------------------------------*/
6916 int
6917 MRIeraseTalairachPlaneNew(MRI *mri, MRI *mri_mask, int orientation, int x,
6918                           int y, int z, int wsize, int fill_val)
6919 {
6920   Real     e1_x, e1_y, e1_z, e2_x, e2_y, e2_z, xbase, ybase, zbase ;
6921   int      whalf, xk, yk, xi, yi, zi, xki, yki, x0, y0 ;
6922   Real     ex, ey, ez, len, xt0, yt0, zt0 ;
6923 
6924   whalf = (wsize-1)/2 ;
6925 
6926   x0 = mri_mask->width/2 ; y0 = mri_mask->height/2 ;
6927   MRIvoxelToTalairachVoxel(mri, x, y, z, &xt0, &yt0, &zt0) ;
6928   switch (orientation)
6929     {
6930     default:
6931     case MRI_CORONAL:   /* basis vectors in x-y plane */
6932       /* the 'x' basis vector */
6933       ex = (Real)xt0+1 ; ey = (Real)yt0 ; ez = (Real)zt0 ;
6934       MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6935       e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6936 
6937       /* the 'y' basis vector */
6938       ex = (Real)xt0 ; ey = (Real)yt0+1 ; ez = (Real)zt0 ;
6939       MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6940       e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6941       break ;
6942     case MRI_HORIZONTAL:  /* basis vectors in x-z plane */
6943       /* the 'x' basis vector */
6944       ex = (Real)xt0+1 ; ey = (Real)yt0 ; ez = (Real)zt0 ;
6945       MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6946       e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6947 
6948       /* the 'y' basis vector */
6949       ex = (Real)xt0 ; ey = (Real)yt0 ; ez = (Real)zt0+1 ;
6950       MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6951       e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6952       break ;
6953     case MRI_SAGITTAL:    /* basis vectors in y-z plane */
6954       /* the 'x' basis vector */
6955       ex = (Real)xt0 ; ey = (Real)yt0 ; ez = (Real)zt0+1.0 ;
6956       MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6957       e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6958 
6959       /* the 'y' basis vector */
6960       ex = (Real)xt0 ; ey = (Real)yt0+1.0 ; ez = (Real)zt0 ;
6961       MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6962       e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6963       break ;
6964     }
6965 
6966   /*
6967      don't want to normalize basis - they are orthonormal in magnet space,
6968      not necessarily Talairach space.
6969   */
6970   len = sqrt(e1_x*e1_x + e1_y*e1_y + e1_z*e1_z) ;
6971   /*  e1_x /= len ; e1_y /= len ; e1_z /= len ;*/
6972   len = sqrt(e2_x*e2_x + e2_y*e2_y + e2_z*e2_z) ;
6973   /*  e2_x /= len ; e2_y /= len ; e2_z /= len ;*/
6974 
6975   for (yk = -whalf ; yk <= whalf ; yk++)
6976     {
6977       xbase = (float)x + (float)yk * e2_x ;
6978       ybase = (float)y + (float)yk * e2_y ;
6979       zbase = (float)z + (float)yk * e2_z ;
6980       for (xk = -whalf ; xk <= whalf ; xk++)
6981         {
6982           /* in-plane vect. is linear combination of scaled basis vects */
6983           xi = mri->xi[nint(xbase + xk*e1_x)] ;
6984           yi = mri->yi[nint(ybase + xk*e1_y)] ;
6985           zi = mri->zi[nint(zbase + xk*e1_z)] ;
6986           xki = mri_mask->xi[xk+x0] ; yki = mri_mask->yi[yk+y0] ;
6987           if (MRIvox(mri_mask, xki, yki,0))
6988             MRIvox(mri, xi, yi, zi) = fill_val ;
6989         }
6990     }
6991 
6992   return(NO_ERROR) ;
6993 }
6994 /*-----------------------------------------------------
6995   Parameters:
6996 
6997   Returns value:
6998 
6999   Description
7000   ------------------------------------------------------*/
7001 int
7002 MRIeraseTalairachPlane(MRI *mri, MRI *mri_mask, int orientation, int x, int y,
7003                        int z, int wsize, int fill_val)
7004 {
7005   Real     e1_x, e1_y, e1_z, e2_x, e2_y, e2_z, xbase, ybase, zbase ;
7006   int      whalf, xk, yk, xi, yi, zi ;
7007   Real     ex, ey, ez, len ;
7008 
7009   whalf = (wsize-1)/2 ;
7010 
7011   switch (orientation)
7012     {
7013     default:
7014     case MRI_CORONAL:   /* basis vectors in x-y plane */
7015       /* the 'x' basis vector */
7016       ex = (Real)x+1 ; ey = (Real)y ; ez = (Real)z ;
7017       MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
7018       e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
7019 
7020       /* the 'y' basis vector */
7021       ex = (Real)x ; ey = (Real)y+1 ; ez = (Real)z ;
7022       MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
7023       e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
7024       break ;
7025     case MRI_HORIZONTAL:  /* basis vectors in x-z plane */
7026       /* the 'x' basis vector */
7027       ex = (Real)x+1 ; ey = (Real)y ; ez = (Real)z ;
7028       MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
7029       e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
7030 
7031       /* the 'y' basis vector */
7032       ex = (Real)x ; ey = (Real)y ; ez = (Real)z+1 ;
7033       MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
7034       e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
7035       break ;
7036     case MRI_SAGITTAL:    /* basis vectors in y-z plane */
7037       /* the 'x' basis vector */
7038       ex = (Real)x ; ey = (Real)y ; ez = (Real)z+1.0 ;
7039       MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
7040       e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
7041 
7042       /* the 'y' basis vector */
7043       ex = (Real)x ; ey = (Real)y+1.0 ; ez = (Real)z ;
7044       MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
7045       e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
7046       break ;
7047     }
7048 
7049   /*
7050      don't want to normalize basis - they are orthonormal in magnet space,
7051      not necessarily Talairach space.
7052   */
7053   len = sqrt(e1_x*e1_x + e1_y*e1_y + e1_z*e1_z) ;
7054   /*  e1_x /= len ; e1_y /= len ; e1_z /= len ;*/
7055   len = sqrt(e2_x*e2_x + e2_y*e2_y + e2_z*e2_z) ;
7056   /*  e2_x /= len ; e2_y /= len ; e2_z /= len ;*/
7057 
7058   for (yk = -whalf ; yk <= whalf ; yk++)
7059     {
7060       xbase = (float)x + (float)yk * e2_x ;
7061       ybase = (float)y + (float)yk * e2_y ;
7062       zbase = (float)z + (float)yk * e2_z ;
7063       for (xk = -whalf ; xk <= whalf ; xk++)
7064         {
7065           /* in-plane vect. is linear combination of scaled basis vects */
7066           xi = mri->xi[nint(xbase + xk*e1_x)] ;
7067           yi = mri->yi[nint(ybase + xk*e1_y)] ;
7068           zi = mri->zi[nint(zbase + xk*e1_z)] ;
7069           if (MRIvox(mri_mask, xk+whalf,yk+whalf,0))
7070             MRIvox(mri, xi, yi, zi) = fill_val ;
7071         }
7072     }
7073 
7074   return(NO_ERROR) ;
7075 }
7076 /*-----------------------------------------------------
7077   Parameters:
7078 
7079   Returns value:
7080 
7081   Description
7082   ------------------------------------------------------*/
7083 MRI *
7084 MRIextractPlane(MRI *mri_src, MRI *mri_dst, int orientation, int where)
7085 {
7086   int      x, y, z, width, height ;
7087 
7088   switch (orientation)
7089     {
7090     default:
7091     case MRI_CORONAL:   /* basis vectors in x-y plane */
7092       width = mri_src->width ; height = mri_src->height ;
7093       break ;
7094     case MRI_HORIZONTAL:  /* basis vectors in x-z plane */
7095       width = mri_src->width ; height = mri_src->depth ;
7096       break ;
7097     case MRI_SAGITTAL:    /* basis vectors in y-z plane */
7098       width = mri_src->depth ; height = mri_src->height ;
7099       break ;
7100     }
7101 
7102   if (!mri_dst)
7103     {
7104       mri_dst = MRIalloc(width, height, 1, MRI_UCHAR) ;
7105       MRIcopyHeader(mri_src, mri_dst) ;
7106       mri_dst->zstart = where ; mri_dst->zend = where+1 ;
7107       mri_dst->imnr0 = 0 ; mri_dst->imnr1 = 1 ;
7108     }
7109   switch (orientation)
7110     {
7111     default:
7112     case MRI_CORONAL:   /* basis vectors in x-y plane */
7113       for (x = 0 ; x < mri_src->width ; x++)
7114         {
7115           for (y = 0 ; y < mri_src->height ; y++)
7116             MRIvox(mri_dst, x, y, 0) = MRIvox(mri_src, x, y, where) ;
7117         }
7118       break ;
7119     case MRI_HORIZONTAL:  /* basis vectors in x-z plane */
7120       for (x = 0 ; x < mri_src->width ; x++)
7121         {
7122           for (z = 0 ; z < mri_src->depth ; z++)
7123             MRIvox(mri_dst, x, z, 0) = MRIvox(mri_src, x, where, z) ;
7124         }
7125       break ;
7126     case MRI_SAGITTAL:    /* basis vectors in y-z plane */
7127       for (z = 0 ; z < mri_src->depth ; z++)
7128         {
7129           for (y = 0 ; y < mri_src->height ; y++)
7130             MRIvox(mri_dst, z, y, 0) = MRIvox(mri_src, where, y, z) ;
7131         }
7132       break ;
7133     }
7134 
7135   return(mri_dst) ;
7136 }
7137 /*-----------------------------------------------------
7138   Parameters:
7139 
7140   Returns value:
7141 
7142   Description
7143   ------------------------------------------------------*/
7144 MRI *
7145 MRIfillPlane
7146 (MRI *mri_mask, MRI *mri_dst, int orientation, int where, int fillval)
7147 {
7148   int      x, y, z, width, height ;
7149 
7150   switch (orientation)
7151     {
7152     default:
7153     case MRI_CORONAL:   /* basis vectors in x-y plane */
7154       width = mri_mask->width ; height = mri_mask->height ;
7155       break ;
7156     case MRI_HORIZONTAL:  /* basis vectors in x-z plane */
7157       width = mri_mask->width ; height = mri_mask->depth ;
7158       break ;
7159     case MRI_SAGITTAL:    /* basis vectors in y-z plane */
7160       width = mri_mask->depth ; height = mri_mask->height ;
7161       break ;
7162     }
7163 
7164   switch (orientation)
7165     {
7166     default:
7167     case MRI_CORONAL:   /* basis vectors in x-y plane */
7168       for (x = 0 ; x < mri_dst->width ; x++)
7169         {
7170           for (y = 0 ; y < mri_dst->height ; y++)
7171             if (MRIvox(mri_mask, x, y, 0))
7172               MRIvox(mri_dst, x, y, where) = fillval ;
7173         }
7174       break ;
7175     case MRI_HORIZONTAL:  /* basis vectors in x-z plane */
7176       for (x = 0 ; x < mri_dst->width ; x++)
7177         {
7178           for (z = 0 ; z < mri_dst->depth ; z++)
7179             {
7180               if (MRIvox(mri_mask, x, z, 0))
7181                 MRIvox(mri_dst, x, where, z) = fillval ;
7182             }
7183         }
7184       break ;
7185     case MRI_SAGITTAL:    /* basis vectors in y-z plane */
7186       for (z = 0 ; z < mri_dst->depth ; z++)
7187         {
7188           for (y = 0 ; y < mri_dst->height ; y++)
7189             if (MRIvox(mri_mask, z, y, 0))
7190               MRIvox(mri_dst, where, y, z) = fillval ;
7191         }
7192       break ;
7193     }
7194 
7195   return(mri_dst) ;
7196 }
7197 /*-----------------------------------------------------
7198   Parameters:
7199 
7200   Returns value:
7201 
7202   Description
7203   ------------------------------------------------------*/
7204 int
7205 MRIerasePlane(MRI *mri, float x0, float y0, float z0,
7206               float dx, float dy, float dz, int fill_val)
7207 {
7208   int      *pxi, *pyi, *pzi, xi, yi, zi, x, y, z ;
7209   float    e1_x, e1_y, e1_z, e2_x, e2_y, e2_z, maxlen, l1, l2 ;
7210 
7211   maxlen = MAX(mri->width, mri->height) ; maxlen = MAX(maxlen, mri->depth) ;
7212 
7213   /* don't care about sign (right-hand rule) */
7214   e1_x = dz*dz - dx*dy ;
7215   e1_y = dx*dx - dy*dz ;
7216   e1_z = dy*dy - dz*dx ;
7217   l1 = sqrt(e1_x*e1_x + e1_y*e1_y + e1_z*e1_z) ;
7218   e1_x /= l1 ; e1_y /= l1 ; e1_z /= l1 ;
7219 
7220   e2_x = e1_y*dz - e1_z*dy ;
7221   e2_y = e1_x*dz - e1_z*dx ;
7222   e2_z = e1_y*dx - e1_x*dy ;
7223   l2 = sqrt(e2_x*e2_x + e2_y*e2_y + e2_z*e2_z) ;
7224   e2_x /= l2 ; e2_y /= l2 ; e2_z /= l2 ;
7225 
7226   pxi = mri->xi ; pyi = mri->yi ; pzi = mri->zi ;
7227   maxlen *= 1.5 ;  /* make sure to get entire extent */
7228   for (l1 = -maxlen/2 ; l1 <= maxlen/2 ; l1 += 0.5f)
7229     {
7230       for (l2 = -maxlen/2 ; l2 <= maxlen/2 ; l2 += 0.5f)
7231         {
7232           x = nint(x0 + l1 * e1_x + l2 * e2_x) ; xi = pxi[x] ;
7233           y = nint(y0 + l1 * e1_y + l2 * e2_y) ; yi = pyi[y] ;
7234           z = nint(z0 + l1 * e1_z + l2 * e2_z) ; zi = pzi[z] ;
7235           MRIvox(mri, xi, yi, zi) = fill_val ;
7236         }
7237     }
7238 
7239   return(NO_ERROR) ;
7240 }
7241 /*-----------------------------------------------------
7242   Parameters:
7243 
7244   Returns value:
7245 
7246   Description
7247   Interpolate the volume to cubic voxels.
7248   ------------------------------------------------------*/
7249 MRI *
7250 MRIinterpolate(MRI *mri_src, MRI *mri_dst)
7251 {
7252   int     xs, ys, zs, xd, yd, zd, max_dim, xorig, yorig, zorig, dorig ;
7253   float   sx, sy, sz, psize ;
7254   int     width, height, depth, i ;
7255   float   xsmd, ysmd, zsmd, xspd, yspd, zspd, weights[8], fout ;
7256   int     xsp, xsm, ysp, ysm, zsp, zsm ;  /* surrounding coordinates */
7257   float vals[8], outval ;
7258 
7259   width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth;
7260   if (width > height)
7261     {
7262       max_dim = width > depth ? width : depth ;
7263       psize = width > depth ? mri_src->xsize : mri_src->zsize ;
7264     }
7265   else
7266     {
7267       max_dim = height > depth ? height : depth ;
7268       psize = height > depth ? mri_src->ysize : mri_src->zsize ;
7269     }
7270 
7271   if (!mri_dst)
7272     {
7273       mri_dst = MRIalloc(max_dim, max_dim, max_dim, mri_src->type) ;
7274       MRIcopyHeader(mri_src, mri_dst) ;
7275     }
7276 
7277   mri_dst->xsize = mri_dst->ysize = mri_dst->zsize = psize ;
7278   sx = (float)width / (float)max_dim  ;
7279   sy = (float)height / (float)max_dim  ;
7280   sz = (float)depth / (float)max_dim  ;
7281 
7282   mri_dst->imnr0 = 1;
7283   mri_dst->imnr1 = mri_dst->depth;
7284   mri_dst->xstart = -mri_dst->xsize * mri_dst->width / 2;
7285   mri_dst->xend = -mri_dst->xstart;
7286   mri_dst->ystart = -mri_dst->ysize * mri_dst->height / 2;
7287   mri_dst->yend = -mri_dst->ystart;
7288   mri_dst->zstart = -mri_dst->zsize * mri_dst->depth / 2;
7289   mri_dst->zend = -mri_dst->zstart;
7290 
7291   xorig = (width-1)/2 ; yorig = (height-1)/2 ; zorig = (depth-1)/2 ;
7292   dorig = (max_dim-1)/2 ;
7293 
7294   /*
7295     for each output voxel, find the 8 nearest input voxels and interpolate
7296     the output voxel from them.
7297   */
7298   for (zd = 0 ; zd < max_dim ; zd++)
7299     {
7300       printf("interpolate: %d/%d\n",zd+1,max_dim);
7301       for (yd = 0 ; yd < max_dim ; yd++)
7302         {
7303           for (xd = 0 ; xd < max_dim ; xd++)
7304             {
7305               /* do trilinear interpolation here */
7306               xs = sx*(xd-dorig) + xorig ;
7307               ys = sy*(yd-dorig) + yorig ;
7308               zs = sz*(zd-dorig) + zorig ;
7309 
7310               /*
7311                  these boundary conditions will cause
7312                  reflection across the border
7313                  for the 1st negative pixel.
7314               */
7315               if (xs > -1 && xs < width &&
7316                   ys > -1 && ys < height &&
7317                   zs > -1 && zs < depth)
7318                 {
7319                   xsm = (int)xs ;
7320                   xsp = MIN(width-1, xsm+1) ;
7321                   ysm = (int)ys ;
7322                   ysp = MIN(height-1, ysm+1) ;
7323                   zsm = (int)zs ;
7324                   zsp = MIN(depth-1, zsm+1) ;
7325                   xsmd = xs - (float)xsm ;
7326                   ysmd = ys - (float)ysm ;
7327                   zsmd = zs - (float)zsm ;
7328                   xspd = (1.0f - xsmd) ;
7329                   yspd = (1.0f - ysmd) ;
7330                   zspd = (1.0f - zsmd) ;
7331 
7332                   /*          vals[0] = mri_src->slices[zsm][ysm][xsm] ;
7333                               vals[1] = mri_src->slices[zsm][ysm][xsp] ;
7334                               vals[2] = mri_src->slices[zsm][ysp][xsm] ;
7335                               vals[3] = mri_src->slices[zsm][ysp][xsp] ;
7336                               vals[4] = mri_src->slices[zsp][ysm][xsm] ;
7337                               vals[5] = mri_src->slices[zsp][ysm][xsp] ;
7338                               vals[6] = mri_src->slices[zsp][ysp][xsm] ;
7339                               vals[7] = mri_src->slices[zsp][ysp][xsp] ;
7340                   */
7341                   /* different vox types... */
7342                   vals[0] = MRIFvox(mri_src, xsm, ysm, zsm);
7343                   vals[1] = MRIFvox(mri_src, xsp, ysm, zsm);
7344                   vals[2] = MRIFvox(mri_src, xsm, ysp, zsm);
7345                   vals[3] = MRIFvox(mri_src, xsp, ysp, zsm);
7346                   vals[4] = MRIFvox(mri_src, xsm, ysm, zsp);
7347                   vals[5] = MRIFvox(mri_src, xsp, ysm, zsp);
7348                   vals[6] = MRIFvox(mri_src, xsm, ysp, zsp);
7349                   vals[7] = MRIFvox(mri_src, xsp, ysp, zsp);
7350 
7351                   weights[0] = zsmd * ysmd * xsmd ;
7352                   weights[1] = zsmd * ysmd * xspd ;
7353                   weights[2] = zsmd * yspd * xsmd ;
7354                   weights[3] = zsmd * yspd * xspd ;
7355                   weights[4] = zspd * ysmd * xsmd ;
7356                   weights[5] = zspd * ysmd * xspd ;
7357                   weights[6] = zspd * yspd * xsmd ;
7358                   weights[7] = zspd * yspd * xspd ;
7359                   /*
7360                     for(i = 0;i < 8;i++)
7361                     printf("%d, %f, %f\n",i,vals[i], weights[i]);
7362                   */
7363                   for (fout = 0.0f, i = 0 ; i < 8 ; i++)
7364                     fout += (float)vals[i] * weights[i] ;
7365                   outval = (float)nint(fout) ;
7366                   MRIvox(mri_dst, xd, yd, zd) = (BUFTYPE)nint(fout) ;
7367 
7368                 }
7369             }
7370         }
7371     }
7372 
7373   mri_dst->ras_good_flag = 0;
7374 
7375   return(mri_dst) ;
7376 }
7377 /*-----------------------------------------------------
7378   Parameters:
7379 
7380   Returns value:
7381 
7382   Description
7383   ------------------------------------------------------*/
7384 int
7385 MRIsampleVolumeFrame(MRI *mri,Real x,Real y,Real z,int frame,Real *pval)
7386 {
7387   int  OutOfBounds;
7388   int  xm, xp, ym, yp, zm, zp, width, height, depth ;
7389   Real val, xmd, ymd, zmd, xpd, ypd, zpd ;  /* d's are distances */
7390 
7391   if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
7392     return(MRIsampleVolumeFrameType
7393            (mri, x, y, z, frame, SAMPLE_NEAREST, pval)) ;
7394 
7395   if (frame >= mri->nframes)
7396     {
7397       *pval = 1.0 ;
7398       return(NO_ERROR) ;
7399     }
7400 
7401   OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7402   if(OutOfBounds == 1){
7403     /* unambiguoulsy out of bounds */
7404     *pval = 0.0;
7405     return(NO_ERROR) ;
7406   }
7407 
7408   width = mri->width ; height = mri->height ; depth = mri->depth ;
7409   if (x >= width)
7410     x = width - 1.0 ;
7411   if (y >= height)
7412     y = height - 1.0 ;
7413   if (z >= depth)
7414     z = depth - 1.0 ;
7415   if (x < 0.0)
7416     x = 0.0 ;
7417   if (y < 0.0)
7418     y = 0.0 ;
7419   if (z < 0.0)
7420     z = 0.0 ;
7421 
7422   xm = MAX((int)x, 0) ;
7423   xp = MIN(width-1, xm+1) ;
7424   ym = MAX((int)y, 0) ;
7425   yp = MIN(height-1, ym+1) ;
7426   zm = MAX((int)z, 0) ;
7427   zp = MIN(depth-1, zm+1) ;
7428 
7429   xmd = x - (float)xm ;
7430   ymd = y - (float)ym ;
7431   zmd = z - (float)zm ;
7432   xpd = (1.0f - xmd) ;
7433   ypd = (1.0f - ymd) ;
7434   zpd = (1.0f - zmd) ;
7435 
7436   switch (mri->type)
7437     {
7438     case MRI_UCHAR:
7439       *pval = val =
7440         xpd * ypd * zpd * (Real)MRIseq_vox(mri, xm, ym, zm, frame) +
7441         xpd * ypd * zmd * (Real)MRIseq_vox(mri, xm, ym, zp, frame) +
7442         xpd * ymd * zpd * (Real)MRIseq_vox(mri, xm, yp, zm, frame) +
7443         xpd * ymd * zmd * (Real)MRIseq_vox(mri, xm, yp, zp, frame) +
7444         xmd * ypd * zpd * (Real)MRIseq_vox(mri, xp, ym, zm, frame) +
7445         xmd * ypd * zmd * (Real)MRIseq_vox(mri, xp, ym, zp, frame) +
7446         xmd * ymd * zpd * (Real)MRIseq_vox(mri, xp, yp, zm, frame) +
7447         xmd * ymd * zmd * (Real)MRIseq_vox(mri, xp, yp, zp, frame) ;
7448       break ;
7449     case MRI_FLOAT:
7450       *pval = val =
7451         xpd * ypd * zpd * (Real)MRIFseq_vox(mri, xm, ym, zm, frame) +
7452         xpd * ypd * zmd * (Real)MRIFseq_vox(mri, xm, ym, zp, frame) +
7453         xpd * ymd * zpd * (Real)MRIFseq_vox(mri, xm, yp, zm, frame) +
7454         xpd * ymd * zmd * (Real)MRIFseq_vox(mri, xm, yp, zp, frame) +
7455         xmd * ypd * zpd * (Real)MRIFseq_vox(mri, xp, ym, zm, frame) +
7456         xmd * ypd * zmd * (Real)MRIFseq_vox(mri, xp, ym, zp, frame) +
7457         xmd * ymd * zpd * (Real)MRIFseq_vox(mri, xp, yp, zm, frame) +
7458         xmd * ymd * zmd * (Real)MRIFseq_vox(mri, xp, yp, zp, frame) ;
7459       break ;
7460     case MRI_SHORT:
7461       *pval = val =
7462         xpd * ypd * zpd * (Real)MRISseq_vox(mri, xm, ym, zm, frame) +
7463         xpd * ypd * zmd * (Real)MRISseq_vox(mri, xm, ym, zp, frame) +
7464         xpd * ymd * zpd * (Real)MRISseq_vox(mri, xm, yp, zm, frame) +
7465         xpd * ymd * zmd * (Real)MRISseq_vox(mri, xm, yp, zp, frame) +
7466         xmd * ypd * zpd * (Real)MRISseq_vox(mri, xp, ym, zm, frame) +
7467         xmd * ypd * zmd * (Real)MRISseq_vox(mri, xp, ym, zp, frame) +
7468         xmd * ymd * zpd * (Real)MRISseq_vox(mri, xp, yp, zm, frame) +
7469         xmd * ymd * zmd * (Real)MRISseq_vox(mri, xp, yp, zp, frame) ;
7470       break ;
7471     case MRI_INT:
7472       *pval = val =
7473         xpd * ypd * zpd * (Real)MRIIseq_vox(mri, xm, ym, zm, frame) +
7474         xpd * ypd * zmd * (Real)MRIIseq_vox(mri, xm, ym, zp, frame) +
7475         xpd * ymd * zpd * (Real)MRIIseq_vox(mri, xm, yp, zm, frame) +
7476         xpd * ymd * zmd * (Real)MRIIseq_vox(mri, xm, yp, zp, frame) +
7477         xmd * ypd * zpd * (Real)MRIIseq_vox(mri, xp, ym, zm, frame) +
7478         xmd * ypd * zmd * (Real)MRIIseq_vox(mri, xp, ym, zp, frame) +
7479         xmd * ymd * zpd * (Real)MRIIseq_vox(mri, xp, yp, zm, frame) +
7480         xmd * ymd * zmd * (Real)MRIIseq_vox(mri, xp, yp, zp, frame) ;
7481       break ;
7482     case MRI_LONG:
7483       *pval = val =
7484         xpd * ypd * zpd * (Real)MRILseq_vox(mri, xm, ym, zm, frame) +
7485         xpd * ypd * zmd * (Real)MRILseq_vox(mri, xm, ym, zp, frame) +
7486         xpd * ymd * zpd * (Real)MRILseq_vox(mri, xm, yp, zm, frame) +
7487         xpd * ymd * zmd * (Real)MRILseq_vox(mri, xm, yp, zp, frame) +
7488         xmd * ypd * zpd * (Real)MRILseq_vox(mri, xp, ym, zm, frame) +
7489         xmd * ypd * zmd * (Real)MRILseq_vox(mri, xp, ym, zp, frame) +
7490         xmd * ymd * zpd * (Real)MRILseq_vox(mri, xp, yp, zm, frame) +
7491         xmd * ymd * zmd * (Real)MRILseq_vox(mri, xp, yp, zp, frame) ;
7492       break ;
7493     default:
7494       ErrorReturn(ERROR_UNSUPPORTED,
7495                   (ERROR_UNSUPPORTED,
7496                    "MRIsampleVolumeFrame: unsupported type %d", mri->type)) ;
7497       break ;
7498     }
7499   return(NO_ERROR) ;
7500 }
7501 
7502 
7503 
7504 /*---------------------------------------------------------------------------
7505   Purpose: to return the approximate fraction of a voxel centered
7506   at the given point
7507   is labeled with a given label by the labeled volume: mri
7508 
7509   Input: mri  is the labeled volume. Ea voxel contains the uchar label index
7510   x,y,z is the floating point location of the center of a voxel
7511   whose labeling is to be determined. The voxel is examined to see
7512   how much of it is labeled with the label, ucharLabel
7513 
7514   Output: pval is the fraction which the given voxel location is labeled
7515   by ucharLabel
7516   returns NO_ERROR or ERROR_UNSUPPORTED if an unsupported
7517   (non-uchar) mri labeled volume is passed in
7518   AAM: 7/26/00
7519   --------------------------------------------------------------------------*/
7520 
7521 #ifndef uchar
7522 #define uchar unsigned char
7523 #endif
7524 int
7525 MRIsampleLabeledVolume
7526 (MRI *mri, Real x, Real y, Real z, Real *pval, unsigned char ucharLabel)
7527 {
7528   /* m's are the mri grid locations less than x (or y or z)
7529      (i.e. floor(x), p's are essentially rounding up  to the next
7530      grid location  greater than x  */
7531   int  xm, xp, ym, yp, zm, zp;
7532   int width, height, depth ;
7533   Real xmd, ymd, zmd, xpd, ypd, zpd ;  /* d's are distances */
7534   uchar ucharDmmm;
7535   uchar ucharDmmp;
7536   uchar ucharDmpm;
7537   uchar ucharDmpp;
7538   uchar ucharDpmm;
7539   uchar ucharDpmp;
7540   uchar ucharDppm;
7541   uchar ucharDppp;
7542 
7543 
7544   *pval=0.0;
7545 
7546 
7547 
7548   width = mri->width ;
7549   height = mri->height ;
7550   depth = mri->depth ;
7551   /*  if (x >= width)
7552       x = width - 1.0 ;
7553       if (y >= height)
7554       y = height - 1.0 ;
7555       if (z >= depth)
7556       z = depth - 1.0 ;
7557       if (x < 0.0)
7558       x = 0.0 ;
7559       if (y < 0.0)
7560       y = 0.0 ;
7561       if (z < 0.0)
7562       z = 0.0 ;
7563   */
7564 
7565   /* if the x,y,z point is out of range
7566      then return that none of the given voxel was labeled by ucharLabel */
7567   if (x >= width) return(NO_ERROR) ;
7568   if (y >= height) return(NO_ERROR) ;
7569   if (z >= depth) return(NO_ERROR) ;
7570   if (x < 0.0) return(NO_ERROR) ;
7571   if (y < 0.0) return(NO_ERROR) ;
7572   if (z < 0.0) return(NO_ERROR) ;
7573 
7574   xm = MAX((int)x, 0) ;
7575   xp = MIN(width-1, xm+1) ;
7576   ym = MAX((int)y, 0) ;
7577   yp = MIN(height-1, ym+1) ;
7578   zm = MAX((int)z, 0) ;
7579   zp = MIN(depth-1, zm+1) ;
7580 
7581   ucharDmmm = MRIvox(mri, xm, ym, zm) == ucharLabel ? 1 : 0;
7582   ucharDmmp = MRIvox(mri, xm, ym, zp) == ucharLabel ? 1 : 0;
7583   ucharDmpm = MRIvox(mri, xm, yp, zm) == ucharLabel ? 1 : 0;
7584   ucharDmpp = MRIvox(mri, xm, yp, zp) == ucharLabel ? 1 : 0;
7585   ucharDpmm = MRIvox(mri, xp, ym, zm) == ucharLabel ? 1 : 0;
7586   ucharDpmp = MRIvox(mri, xp, ym, zp) == ucharLabel ? 1 : 0;
7587   ucharDppm = MRIvox(mri, xp, yp, zm) == ucharLabel ? 1 : 0;
7588   ucharDppp = MRIvox(mri, xp, yp, zp) == ucharLabel ? 1 : 0;
7589 
7590   xmd = x - (float)xm ;
7591   ymd = y - (float)ym ;
7592   zmd = z - (float)zm ;
7593   xpd = (1.0f - xmd) ;
7594   ypd = (1.0f - ymd) ;
7595   zpd = (1.0f - zmd) ;
7596 
7597 
7598 
7599   switch (mri->type)
7600     {
7601     case MRI_UCHAR:
7602       *pval =
7603         xpd * ypd * zpd * (Real)ucharDmmm +
7604         xpd * ypd * zmd * (Real)ucharDmmp +
7605         xpd * ymd * zpd * (Real)ucharDmpm +
7606         xpd * ymd * zmd * (Real)ucharDmpp +
7607         xmd * ypd * zpd * (Real)ucharDpmm +
7608         xmd * ypd * zmd * (Real)ucharDpmp +
7609         xmd * ymd * zpd * (Real)ucharDppm +
7610         xmd * ymd * zmd * (Real)ucharDppp ;
7611       break ;
7612     default:
7613       ErrorReturn(ERROR_UNSUPPORTED,
7614                   (ERROR_UNSUPPORTED,
7615                    "MRIsampleVolume: unsupported type %d", mri->type)) ;
7616       break ;
7617     }
7618   return(NO_ERROR) ;
7619 }
7620 /*-----------------------------------------------------
7621   Parameters:
7622 
7623   Returns value:
7624 
7625   Description
7626   ------------------------------------------------------*/
7627 int
7628 MRIsampleVolumeType(MRI *mri, Real x, Real y, Real z, Real *pval, int type)
7629 {
7630   int   xv, yv, zv ;
7631   int OutOfBounds;
7632 
7633   switch (type)
7634     {
7635     default:
7636     case SAMPLE_NEAREST:
7637       break ;
7638     case SAMPLE_TRILINEAR:
7639       return(MRIsampleVolume(mri, x, y, z, pval)) ;
7640     case SAMPLE_CUBIC:
7641       return(MRIcubicSampleVolume(mri, x, y, z, pval)) ;
7642     case SAMPLE_SINC:
7643       return(MRIsincSampleVolume(mri, x, y, z, 5, pval)) ;
7644     }
7645 
7646   OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7647   if(OutOfBounds == 1){
7648     /* unambiguously out of bounds */
7649     *pval = 0.0;
7650     return(NO_ERROR) ;
7651   }
7652 
7653   xv = nint(x) ; yv = nint(y) ; zv = nint(z) ;
7654   if (xv < 0)
7655     xv = 0 ;
7656   if (xv >= mri->width)
7657     xv = mri->width-1 ;
7658   if (yv < 0)
7659     yv = 0 ;
7660   if (yv >= mri->height)
7661     yv = mri->height-1 ;
7662   if (zv < 0)
7663     zv = 0 ;
7664   if (zv >= mri->depth)
7665     zv = mri->depth-1 ;
7666 
7667   switch (mri->type)
7668     {
7669     case MRI_UCHAR:
7670       *pval = (float)MRIvox(mri, xv, yv, zv) ;
7671       break ;
7672     case MRI_SHORT:
7673       *pval = (float)MRISvox(mri, xv, yv, zv) ;
7674       break ;
7675     case MRI_INT:
7676       *pval = (float)MRIIvox(mri, xv, yv, zv) ;
7677       break ;
7678     case MRI_FLOAT:
7679       *pval = MRIFvox(mri, xv, yv, zv) ;
7680       break ;
7681     default:
7682       *pval = 0 ;
7683       ErrorReturn
7684         (ERROR_UNSUPPORTED,
7685          (ERROR_UNSUPPORTED,
7686           "MRIsampleVolumeType: unsupported volume type %d",
7687           mri->type)) ;
7688     }
7689   return(NO_ERROR) ;
7690 }
7691 /*-----------------------------------------------------
7692   Parameters:
7693 
7694   Returns value:
7695 
7696   Description
7697   ------------------------------------------------------*/
7698 int
7699 MRIsampleVolumeFrameType
7700 (MRI *mri, Real x, Real y, Real z, int frame, int type, Real *pval)
7701 {
7702   int   xv, yv, zv ;
7703   int OutOfBounds;
7704 
7705   if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
7706     type = SAMPLE_NEAREST ;
7707 
7708   switch (type)
7709     {
7710     case SAMPLE_NEAREST:
7711       break ;
7712     case SAMPLE_TRILINEAR:
7713       return(MRIsampleVolumeFrame(mri, x, y, z, frame, pval)) ;
7714     default:
7715       /*E* add SAMPLE_CUBIC here? */
7716     case SAMPLE_SINC:
7717       ErrorReturn
7718         (ERROR_UNSUPPORTED,
7719          (ERROR_UNSUPPORTED,
7720           "MRIsampleVolumeFrameType(%d): unsupported interpolation type",
7721           type));
7722       /*    return(MRIsincSampleVolume(mri, x, y, z, 5, pval)) ;*/
7723     }
7724 
7725   OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7726   if(OutOfBounds == 1){
7727     /* unambiguously out of bounds */
7728     *pval = 0.0;
7729     return(NO_ERROR) ;
7730   }
7731 
7732   xv = nint(x) ; yv = nint(y) ; zv = nint(z) ;
7733   if (xv < 0)
7734     xv = 0 ;
7735   if (xv >= mri->width)
7736     xv = mri->width-1 ;
7737   if (yv < 0)
7738     yv = 0 ;
7739   if (yv >= mri->height)
7740     yv = mri->height-1 ;
7741   if (zv < 0)
7742     zv = 0 ;
7743   if (zv >= mri->depth)
7744     zv = mri->depth-1 ;
7745 
7746   switch (mri->type)
7747     {
7748     case MRI_UCHAR:
7749       *pval = (float)MRIseq_vox(mri, xv, yv, zv, frame) ;
7750       break ;
7751     case MRI_SHORT:
7752       *pval = (float)MRISseq_vox(mri, xv, yv, zv, frame) ;
7753       break ;
7754     case MRI_INT:
7755       *pval = (float)MRIIseq_vox(mri, xv, yv, zv, frame) ;
7756       break ;
7757     case MRI_FLOAT:
7758       *pval = MRIFseq_vox(mri, xv, yv, zv, frame) ;
7759       break ;
7760     default:
7761       *pval = 0 ;
7762       ErrorReturn
7763         (ERROR_UNSUPPORTED,
7764          (ERROR_UNSUPPORTED,
7765           "MRIsampleVolumeFrameType: unsupported volume type %d",
7766           mri->type)) ;
7767     }
7768   return(NO_ERROR) ;
7769 }
7770 
7771 
7772 int
7773 MRIinterpolateIntoVolume(MRI *mri, Real x, Real y, Real z, Real val)
7774 {
7775   int  OutOfBounds;
7776   int  xm, xp, ym, yp, zm, zp, width, height, depth ;
7777   Real xmd, ymd, zmd, xpd, ypd, zpd ;  /* d's are distances */
7778 
7779   OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7780   if(OutOfBounds == 1){
7781     /* unambiguously out of bounds */
7782     return(NO_ERROR) ;
7783   }
7784 
7785   width = mri->width ; height = mri->height ; depth = mri->depth ;
7786 
7787   if (x >= width)    x = width - 1.0 ;
7788   if (y >= height)   y = height - 1.0 ;
7789   if (z >= depth)    z = depth - 1.0 ;
7790   if (x < 0.0)       x = 0.0 ;
7791   if (y < 0.0)       y = 0.0 ;
7792   if (z < 0.0)       z = 0.0 ;
7793 
7794   xm = MAX((int)x, 0) ;
7795   xp = MIN(width-1, xm+1) ;
7796   ym = MAX((int)y, 0) ;
7797   yp = MIN(height-1, ym+1) ;
7798   zm = MAX((int)z, 0) ;
7799   zp = MIN(depth-1, zm+1) ;
7800 
7801   xmd = x - (float)xm ;
7802   ymd = y - (float)ym ;
7803   zmd = z - (float)zm ;
7804   xpd = (1.0f - xmd) ;
7805   ypd = (1.0f - ymd) ;
7806   zpd = (1.0f - zmd) ;
7807 
7808   switch (mri->type)
7809     {
7810     case MRI_UCHAR:
7811       MRIvox(mri, xm, ym, zm) += nint(xpd * ypd * zpd * val) ;
7812       MRIvox(mri, xm, ym, zp) += nint(xpd * ypd * zmd * val) ;
7813       MRIvox(mri, xm, yp, zm) += nint(xpd * ymd * zpd * val) ;
7814       MRIvox(mri, xm, yp, zp) += nint(xpd * ymd * zmd * val) ;
7815       MRIvox(mri, xp, ym, zm) += nint(xmd * ypd * zpd * val) ;
7816       MRIvox(mri, xp, ym, zp) += nint(xmd * ypd * zmd * val) ;
7817       MRIvox(mri, xp, yp, zm) += nint(xmd * ymd * zpd * val) ;
7818       MRIvox(mri, xp, yp, zp) += nint(xmd * ymd * zmd * val) ;
7819       break ;
7820     case MRI_FLOAT:
7821       MRIFvox(mri, xm, ym, zm) += (xpd * ypd * zpd * val) ;
7822       MRIFvox(mri, xm, ym, zp) += (xpd * ypd * zmd * val) ;
7823       MRIFvox(mri, xm, yp, zm) += (xpd * ymd * zpd * val) ;
7824       MRIFvox(mri, xm, yp, zp) += (xpd * ymd * zmd * val) ;
7825       MRIFvox(mri, xp, ym, zm) += (xmd * ypd * zpd * val) ;
7826       MRIFvox(mri, xp, ym, zp) += (xmd * ypd * zmd * val) ;
7827       MRIFvox(mri, xp, yp, zm) += (xmd * ymd * zpd * val) ;
7828       MRIFvox(mri, xp, yp, zp) += (xmd * ymd * zmd * val) ;
7829       break ;
7830     case MRI_SHORT:
7831       MRISvox(mri, xm, ym, zm) += nint(xpd * ypd * zpd * val) ;
7832       MRISvox(mri, xm, ym, zp) += nint(xpd * ypd * zmd * val) ;
7833       MRISvox(mri, xm, yp, zm) += nint(xpd * ymd * zpd * val) ;
7834       MRISvox(mri, xm, yp, zp) += nint(xpd * ymd * zmd * val) ;
7835       MRISvox(mri, xp, ym, zm) += nint(xmd * ypd * zpd * val) ;
7836       MRISvox(mri, xp, ym, zp) += nint(xmd * ypd * zmd * val) ;
7837       MRISvox(mri, xp, yp, zm) += nint(xmd * ymd * zpd * val) ;
7838       MRISvox(mri, xp, yp, zp) += nint(xmd * ymd * zmd * val) ;
7839       break ;
7840     case MRI_INT:
7841       MRIIvox(mri, xm, ym, zm) += nint(xpd * ypd * zpd * val) ;
7842       MRIIvox(mri, xm, ym, zp) += nint(xpd * ypd * zmd * val) ;
7843       MRIIvox(mri, xm, yp, zm) += nint(xpd * ymd * zpd * val) ;
7844       MRIIvox(mri, xm, yp, zp) += nint(xpd * ymd * zmd * val) ;
7845       MRIIvox(mri, xp, ym, zm) += nint(xmd * ypd * zpd * val) ;
7846       MRIIvox(mri, xp, ym, zp) += nint(xmd * ypd * zmd * val) ;
7847       MRIIvox(mri, xp, yp, zm) += nint(xmd * ymd * zpd * val) ;
7848       MRIIvox(mri, xp, yp, zp) += nint(xmd * ymd * zmd * val) ;
7849       break ;
7850     case MRI_LONG:
7851       MRILvox(mri, xm, ym, zm) += nint(xpd * ypd * zpd * val) ;
7852       MRILvox(mri, xm, ym, zp) += nint(xpd * ypd * zmd * val) ;
7853       MRILvox(mri, xm, yp, zm) += nint(xpd * ymd * zpd * val) ;
7854       MRILvox(mri, xm, yp, zp) += nint(xpd * ymd * zmd * val) ;
7855       MRILvox(mri, xp, ym, zm) += nint(xmd * ypd * zpd * val) ;
7856       MRILvox(mri, xp, ym, zp) += nint(xmd * ypd * zmd * val) ;
7857       MRILvox(mri, xp, yp, zm) += nint(xmd * ymd * zpd * val) ;
7858       MRILvox(mri, xp, yp, zp) += nint(xmd * ymd * zmd * val) ;
7859       break ;
7860     default:
7861       ErrorReturn(ERROR_UNSUPPORTED,
7862                   (ERROR_UNSUPPORTED,
7863                    "MRIsampleVolume: unsupported type %d", mri->type)) ;
7864       break ;
7865     }
7866   return(NO_ERROR) ;
7867 }
7868 
7869 /*-------------------------------------------------------------------
7870   MRIsampleVolume() - performs trilinear interpolation on a
7871   single-frame volume. See MRIsampleSeqVolume() for sampling
7872   multi-frame.
7873   -------------------------------------------------------------------*/
7874 int
7875 MRIsampleVolume(MRI *mri, Real x, Real y, Real z, Real *pval)
7876 {
7877   int  OutOfBounds;
7878   int  xm, xp, ym, yp, zm, zp, width, height, depth ;
7879   Real val, xmd, ymd, zmd, xpd, ypd, zpd ;  /* d's are distances */
7880 
7881   if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
7882     return(MRIsampleVolumeType(mri, x, y, z, pval, SAMPLE_NEAREST)) ;
7883 
7884   OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7885   if(OutOfBounds == 1){
7886     /* unambiguously out of bounds */
7887     *pval = 0.0;
7888     return(NO_ERROR) ;
7889   }
7890 
7891   width = mri->width ; height = mri->height ; depth = mri->depth ;
7892 
7893   if (x >= width)    x = width - 1.0 ;
7894   if (y >= height)   y = height - 1.0 ;
7895   if (z >= depth)    z = depth - 1.0 ;
7896   if (x < 0.0)       x = 0.0 ;
7897   if (y < 0.0)       y = 0.0 ;
7898   if (z < 0.0)       z = 0.0 ;
7899 
7900   xm = MAX((int)x, 0) ;
7901   xp = MIN(width-1, xm+1) ;
7902   ym = MAX((int)y, 0) ;
7903   yp = MIN(height-1, ym+1) ;
7904   zm = MAX((int)z, 0) ;
7905   zp = MIN(depth-1, zm+1) ;
7906 
7907   xmd = x - (float)xm ;
7908   ymd = y - (float)ym ;
7909   zmd = z - (float)zm ;
7910   xpd = (1.0f - xmd) ;
7911   ypd = (1.0f - ymd) ;
7912   zpd = (1.0f - zmd) ;
7913 
7914   switch (mri->type)
7915     {
7916     case MRI_UCHAR:
7917       *pval = val =
7918         xpd * ypd * zpd * (Real)MRIvox(mri, xm, ym, zm) +
7919         xpd * ypd * zmd * (Real)MRIvox(mri, xm, ym, zp) +
7920         xpd * ymd * zpd * (Real)MRIvox(mri, xm, yp, zm) +
7921         xpd * ymd * zmd * (Real)MRIvox(mri, xm, yp, zp) +
7922         xmd * ypd * zpd * (Real)MRIvox(mri, xp, ym, zm) +
7923         xmd * ypd * zmd * (Real)MRIvox(mri, xp, ym, zp) +
7924         xmd * ymd * zpd * (Real)MRIvox(mri, xp, yp, zm) +
7925         xmd * ymd * zmd * (Real)MRIvox(mri, xp, yp, zp) ;
7926       break ;
7927     case MRI_FLOAT:
7928       *pval = val =
7929         xpd * ypd * zpd * (Real)MRIFvox(mri, xm, ym, zm) +
7930         xpd * ypd * zmd * (Real)MRIFvox(mri, xm, ym, zp) +
7931         xpd * ymd * zpd * (Real)MRIFvox(mri, xm, yp, zm) +
7932         xpd * ymd * zmd * (Real)MRIFvox(mri, xm, yp, zp) +
7933         xmd * ypd * zpd * (Real)MRIFvox(mri, xp, ym, zm) +
7934         xmd * ypd * zmd * (Real)MRIFvox(mri, xp, ym, zp) +
7935         xmd * ymd * zpd * (Real)MRIFvox(mri, xp, yp, zm) +
7936         xmd * ymd * zmd * (Real)MRIFvox(mri, xp, yp, zp) ;
7937       break ;
7938     case MRI_SHORT:
7939       *pval = val =
7940         xpd * ypd * zpd * (Real)MRISvox(mri, xm, ym, zm) +
7941         xpd * ypd * zmd * (Real)MRISvox(mri, xm, ym, zp) +
7942         xpd * ymd * zpd * (Real)MRISvox(mri, xm, yp, zm) +
7943         xpd * ymd * zmd * (Real)MRISvox(mri, xm, yp, zp) +
7944         xmd * ypd * zpd * (Real)MRISvox(mri, xp, ym, zm) +
7945         xmd * ypd * zmd * (Real)MRISvox(mri, xp, ym, zp) +
7946         xmd * ymd * zpd * (Real)MRISvox(mri, xp, yp, zm) +
7947         xmd * ymd * zmd * (Real)MRISvox(mri, xp, yp, zp) ;
7948       break ;
7949     case MRI_INT:
7950       *pval = val =
7951         xpd * ypd * zpd * (Real)MRIIvox(mri, xm, ym, zm) +
7952         xpd * ypd * zmd * (Real)MRIIvox(mri, xm, ym, zp) +
7953         xpd * ymd * zpd * (Real)MRIIvox(mri, xm, yp, zm) +
7954         xpd * ymd * zmd * (Real)MRIIvox(mri, xm, yp, zp) +
7955         xmd * ypd * zpd * (Real)MRIIvox(mri, xp, ym, zm) +
7956         xmd * ypd * zmd * (Real)MRIIvox(mri, xp, ym, zp) +
7957         xmd * ymd * zpd * (Real)MRIIvox(mri, xp, yp, zm) +
7958         xmd * ymd * zmd * (Real)MRIIvox(mri, xp, yp, zp) ;
7959       break ;
7960     case MRI_LONG:
7961       *pval = val =
7962         xpd * ypd * zpd * (Real)MRILvox(mri, xm, ym, zm) +
7963         xpd * ypd * zmd * (Real)MRILvox(mri, xm, ym, zp) +
7964         xpd * ymd * zpd * (Real)MRILvox(mri, xm, yp, zm) +
7965         xpd * ymd * zmd * (Real)MRILvox(mri, xm, yp, zp) +
7966         xmd * ypd * zpd * (Real)MRILvox(mri, xp, ym, zm) +
7967         xmd * ypd * zmd * (Real)MRILvox(mri, xp, ym, zp) +
7968         xmd * ymd * zpd * (Real)MRILvox(mri, xp, yp, zm) +
7969         xmd * ymd * zmd * (Real)MRILvox(mri, xp, yp, zp) ;
7970       break ;
7971     default:
7972       ErrorReturn(ERROR_UNSUPPORTED,
7973                   (ERROR_UNSUPPORTED,
7974                    "MRIsampleVolume: unsupported type %d", mri->type)) ;
7975       break ;
7976     }
7977   return(NO_ERROR) ;
7978 }
7979 
7980 /*------------------------------------------------------------------
7981   MRIsampleSeqVolume() - performs trilinear interpolation on a
7982   multi-frame volume. valvect is a vector of length nframes. No error
7983   checking for first and last frame. The caller is able to specify
7984   first frame and last frame so that all frames do not have to be
7985   sampled at the same time (this can be important in time-sensative
7986   applications).
7987   -------------------------------------------------------------------*/
7988 int MRIsampleSeqVolume(MRI *mri, Real x, Real y, Real z, float *valvect,
7989                        int firstframe, int lastframe)
7990 {
7991   int  OutOfBounds;
7992   int  f,xm, xp, ym, yp, zm, zp, width, height, depth ;
7993   Real xmd, ymd, zmd, xpd, ypd, zpd ;  /* d's are distances */
7994 
7995   OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7996   if(OutOfBounds == 1){
7997     /* unambiguously out of bounds */
7998     for(f=firstframe; f <= lastframe; f++) valvect[f] = 0.0;
7999     return(NO_ERROR) ;
8000   }
8001 
8002   width = mri->width ; height = mri->height ; depth = mri->depth ;
8003 
8004   if (x >= width)    x = width - 1.0 ;
8005   if (y >= height)   y = height - 1.0 ;
8006   if (z >= depth)    z = depth - 1.0 ;
8007   if (x < 0.0)       x = 0.0 ;
8008   if (y < 0.0)       y = 0.0 ;
8009   if (z < 0.0)       z = 0.0 ;
8010 
8011   xm = MAX((int)x, 0) ;
8012   xp = MIN(width-1, xm+1) ;
8013   ym = MAX((int)y, 0) ;
8014   yp = MIN(height-1, ym+1) ;
8015   zm = MAX((int)z, 0) ;
8016   zp = MIN(depth-1, zm+1) ;
8017 
8018   xmd = x - (float)xm ;
8019   ymd = y - (float)ym ;
8020   zmd = z - (float)zm ;
8021   xpd = (1.0f - xmd) ;
8022   ypd = (1.0f - ymd) ;
8023   zpd = (1.0f - zmd) ;
8024 
8025   for(f = firstframe; f <= lastframe; f++){
8026     switch (mri->type) {
8027     case MRI_UCHAR:
8028       valvect[f] =
8029         xpd * ypd * zpd * (Real)MRIseq_vox(mri, xm, ym, zm, f) +
8030         xpd * ypd * zmd * (Real)MRIseq_vox(mri, xm, ym, zp, f) +
8031         xpd * ymd * zpd * (Real)MRIseq_vox(mri, xm, yp, zm, f) +
8032         xpd * ymd * zmd * (Real)MRIseq_vox(mri, xm, yp, zp, f) +
8033         xmd * ypd * zpd * (Real)MRIseq_vox(mri, xp, ym, zm, f) +
8034         xmd * ypd * zmd * (Real)MRIseq_vox(mri, xp, ym, zp, f) +
8035         xmd * ymd * zpd * (Real)MRIseq_vox(mri, xp, yp, zm, f) +
8036         xmd * ymd * zmd * (Real)MRIseq_vox(mri, xp, yp, zp, f) ;
8037       break ;
8038     case MRI_FLOAT:
8039       valvect[f] =
8040         xpd * ypd * zpd * (Real)MRIFseq_vox(mri, xm, ym, zm, f) +
8041         xpd * ypd * zmd * (Real)MRIFseq_vox(mri, xm, ym, zp, f) +
8042         xpd * ymd * zpd * (Real)MRIFseq_vox(mri, xm, yp, zm, f) +
8043         xpd * ymd * zmd * (Real)MRIFseq_vox(mri, xm, yp, zp, f) +
8044         xmd * ypd * zpd * (Real)MRIFseq_vox(mri, xp, ym, zm, f) +
8045         xmd * ypd * zmd * (Real)MRIFseq_vox(mri, xp, ym, zp, f) +
8046         xmd * ymd * zpd * (Real)MRIFseq_vox(mri, xp, yp, zm, f) +
8047         xmd * ymd * zmd * (Real)MRIFseq_vox(mri, xp, yp, zp, f) ;
8048       break ;
8049     case MRI_SHORT:
8050       valvect[f] =
8051         xpd * ypd * zpd * (Real)MRISseq_vox(mri, xm, ym, zm, f) +
8052         xpd * ypd * zmd * (Real)MRISseq_vox(mri, xm, ym, zp, f) +
8053         xpd * ymd * zpd * (Real)MRISseq_vox(mri, xm, yp, zm, f) +
8054         xpd * ymd * zmd * (Real)MRISseq_vox(mri, xm, yp, zp, f) +
8055         xmd * ypd * zpd * (Real)MRISseq_vox(mri, xp, ym, zm, f) +
8056         xmd * ypd * zmd * (Real)MRISseq_vox(mri, xp, ym, zp, f) +
8057         xmd * ymd * zpd * (Real)MRISseq_vox(mri, xp, yp, zm, f) +
8058         xmd * ymd * zmd * (Real)MRISseq_vox(mri, xp, yp, zp, f) ;
8059       break ;
8060     case MRI_INT:
8061       valvect[f] =
8062         xpd * ypd * zpd * (Real)MRIIseq_vox(mri, xm, ym, zm, f) +
8063         xpd * ypd * zmd * (Real)MRIIseq_vox(mri, xm, ym, zp, f) +
8064         xpd * ymd * zpd * (Real)MRIIseq_vox(mri, xm, yp, zm, f) +
8065         xpd * ymd * zmd * (Real)MRIIseq_vox(mri, xm, yp, zp, f) +
8066         xmd * ypd * zpd * (Real)MRIIseq_vox(mri, xp, ym, zm, f) +
8067         xmd * ypd * zmd * (Real)MRIIseq_vox(mri, xp, ym, zp, f) +
8068         xmd * ymd * zpd * (Real)MRIIseq_vox(mri, xp, yp, zm, f) +
8069         xmd * ymd * zmd * (Real)MRIIseq_vox(mri, xp, yp, zp, f) ;
8070       break ;
8071     case MRI_LONG:
8072       valvect[f] =
8073         xpd * ypd * zpd * (Real)MRILseq_vox(mri, xm, ym, zm, f) +
8074         xpd * ypd * zmd * (Real)MRILseq_vox(mri, xm, ym, zp, f) +
8075         xpd * ymd * zpd * (Real)MRILseq_vox(mri, xm, yp, zm, f) +
8076         xpd * ymd * zmd * (Real)MRILseq_vox(mri, xm, yp, zp, f) +
8077         xmd * ypd * zpd * (Real)MRILseq_vox(mri, xp, ym, zm, f) +
8078         xmd * ypd * zmd * (Real)MRILseq_vox(mri, xp, ym, zp, f) +
8079         xmd * ymd * zpd * (Real)MRILseq_vox(mri, xp, yp, zm, f) +
8080         xmd * ymd * zmd * (Real)MRILseq_vox(mri, xp, yp, zp, f) ;
8081       break ;
8082     default:
8083       ErrorReturn(ERROR_UNSUPPORTED,
8084                   (ERROR_UNSUPPORTED,
8085                    "MRIsampleSeqVolume: unsupported type %d", mri->type)) ;
8086       break ;
8087     }
8088   }/* end loop over frames */
8089 
8090   return(NO_ERROR) ;
8091 }
8092 
8093 /*-----------------------------------------------------
8094   used by MRIcubicSampleVolume
8095   ------------------------------------------------------*/
8096 
8097 double
8098 localeval(Real x, int iter)
8099 {
8100   double p;
8101   switch (iter)
8102     {
8103     case 0:
8104       p = ((2-x)*x-1)*x; break;
8105     case 1:
8106       p = (3*x-5)*x*x+2; break;
8107     case 2:
8108       p = ((4-3*x)*x+1)*x; break;
8109     case 3:
8110       p = (x-1)*x*x; break;
8111     default:
8112       ErrorReturn(ERROR_UNSUPPORTED,
8113                   (ERROR_UNSUPPORTED,
8114                    "localeval: called wrong by MRIcubicSampleVolume!")) ;
8115     }
8116   return(p);
8117 }
8118 
8119 /*-----------------------------------------------------
8120   Parameters:
8121 
8122   Returns value:
8123 
8124   Description
8125 
8126   by analogy with
8127   /usr/pubsw/common/matlab/6.5/toolbox/matlab/polyfun/interp3.m
8128 
8129   uses localeval above
8130 
8131   ------------------------------------------------------*/
8132 int
8133 MRIcubicSampleVolume(MRI *mri, Real x, Real y, Real z, Real *pval)
8134 {
8135   int  OutOfBounds;
8136   int  width, height, depth ;
8137   int ix_low,iy_low,iz_low,ix,iy,iz;
8138   double val,xx,yy,zz,fx,fy,fz,vv[4][4][4];
8139 
8140   if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
8141     return(MRIsampleVolumeType(mri, x, y, z, pval, SAMPLE_NEAREST)) ;
8142 
8143   OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
8144   if(OutOfBounds == 1){
8145     /* unambiguously out of bounds */
8146     *pval = val = 0.0;
8147     return(NO_ERROR) ;
8148   }
8149   width = mri->width ; height = mri->height ; depth = mri->depth ;
8150 
8151   /*E* I suppose these are for "ambiguously out of bounds" - within .5vox */
8152 
8153   /*E* I think this needs an edit - x is Real, whatever that is, not
8154     int, so any x>= width-1 should be set to width-1.
8155     if (x >= width)    x = width - 1.0 ;
8156     if (y >= height)   y = height - 1.0 ;
8157     if (z >= depth)    z = depth - 1.0 ;
8158   */
8159 
8160   if (x > width-1.0)    x = width - 1.0 ;
8161   if (y > height-1.0)   y = height - 1.0 ;
8162   if (z > depth-1.0)    z = depth - 1.0 ;
8163   if (x < 0.0)       x = 0.0 ;
8164   if (y < 0.0)       y = 0.0 ;
8165   if (z < 0.0)       z = 0.0 ;
8166 
8167   ix_low = floor((double)x);
8168   if ((ix_low = floor((double)x)) < width-1)
8169     xx = x - ix_low;
8170   else
8171     {
8172       ix_low--;
8173       xx = 1;
8174     }
8175   iy_low = floor((double)y);
8176   if ((iy_low = floor((double)y)) < height-1)
8177     yy = y - iy_low;
8178   else
8179     {
8180       iy_low--;
8181       yy = 1;
8182     }
8183   iz_low = floor((double)z);
8184   if ((iz_low = floor((double)z)) < depth-1)
8185     zz = z - iz_low;
8186   else
8187     {
8188       iz_low--;
8189       zz = 1;
8190     }
8191 
8192   /*E* build a little box of the local points plus boundary stuff -
8193     for this rev accept zeroes for the border expansion */
8194 
8195   for(iz= MAX(0,1-iz_low); iz<MIN(4,depth+1-iz_low); iz++)
8196     {
8197       for(iy= MAX(0,1-iy_low); iy<MIN(4,height+1-iy_low); iy++)
8198         {
8199           for(ix= MAX(0,1-ix_low); ix<MIN(4,width+1-ix_low); ix++)
8200             {
8201               switch (mri->type)
8202                 {
8203                 case MRI_UCHAR:
8204                   vv[ix][iy][iz] =
8205                     (double)MRIvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8206                   break;
8207                 case MRI_FLOAT:
8208                   vv[ix][iy][iz] =
8209                     (double)MRIFvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8210                   break;
8211                 case MRI_SHORT:
8212                   vv[ix][iy][iz] =
8213                     (double)MRISvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8214                   break;
8215                 case MRI_INT:
8216                   vv[ix][iy][iz] =
8217                     (double)MRIIvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8218                   break;
8219                 case MRI_LONG:
8220                   vv[ix][iy][iz] =
8221                     (double)MRILvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8222                   break;
8223                 default:
8224                   ErrorReturn(ERROR_UNSUPPORTED,
8225                               (ERROR_UNSUPPORTED,
8226                                "MRIcubicSampleVolume: unsupported type %d",
8227                                mri->type)) ;
8228                   break ;
8229                 }
8230             }
8231         }
8232     }
8233 
8234   val = 0;
8235 
8236   for(iz=0; iz<=3; iz++)
8237     {
8238       fz = localeval(zz,iz);
8239       for(iy=0; iy<=3; iy++)
8240         {
8241           fy = localeval(yy,iy);
8242           for(ix=0; ix<=3; ix++)
8243             {
8244               fx = localeval(xx,ix);
8245               val += (Real)(vv[ix][iy][iz]*fx*fy*fz);
8246             }
8247         }
8248     }
8249 
8250   *pval = val/8.;
8251 
8252   return(NO_ERROR);
8253 }
8254 
8255 /*-----------------------------------------------------
8256   Parameters:
8257 
8258   Returns value:
8259 
8260   Description
8261   ------------------------------------------------------*/
8262 #define IMIN(a,b) (a < b ? a : b)
8263 #define IMAX(a,b) (a > b ? a : b)
8264 double ham_sinc(double x,double fullwidth)
8265 {
8266   double ham;
8267   if( fabs(x) < 1.0e-5)
8268     ham = 1.0;
8269   else {
8270     ham = sin(PI*x)/(PI*x);
8271     ham *= 0.54 + 0.46 * cos(2.0*PI*x/fullwidth);
8272   }
8273   return ham;
8274 }
8275 
8276 /*-------------------------------------------------------------------------*/
8277 int
8278 MRIsincSampleVolume(MRI *mri, Real x, Real y, Real z, int hw, Real *pval)
8279 {
8280 
8281   int  OutOfBounds;
8282   int  width, height, depth ;
8283   int nwidth;
8284   int ix_low,ix_high,iy_low,iy_high,iz_low,iz_high;
8285   int jx1,jy1,jz1,jx_rel,jy_rel,jz_rel;
8286   double coeff_x[128],coeff_y[128],coeff_z[128];
8287   double coeff_x_sum,coeff_y_sum,coeff_z_sum;
8288   double sum_x,sum_y,sum_z;
8289   double xsize,ysize,zsize;
8290 
8291   OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
8292   if(OutOfBounds == 1){
8293     /* unambiguously out of bounds */
8294     *pval = 0.0;
8295     return(NO_ERROR) ;
8296   }
8297 
8298   xsize = mri->xsize; ysize=mri->ysize; zsize=mri->zsize;
8299   width = mri->width ; height = mri->height ; depth = mri->depth ;
8300   if (x >= width)    x = width - 1.0 ;
8301   if (y >= height)   y = height - 1.0 ;
8302   if (z >= depth)    z = depth - 1.0 ;
8303   if (x < 0.0)       x = 0.0 ;
8304   if (y < 0.0)       y = 0.0 ;
8305   if (z < 0.0)       z = 0.0 ;
8306 
8307   nwidth = hw;
8308   ix_low = floor((double)x);
8309   ix_high = ceil((double)x);
8310   iy_low = floor((double)y);
8311   iy_high = ceil((double)y);
8312   iz_low = floor((double)z);
8313   iz_high = ceil((double)z);
8314 
8315   coeff_x_sum = coeff_y_sum = coeff_z_sum = 0;
8316   if(iz_low>=0 && iz_high < depth)
8317     {
8318       for (jx1=IMAX(ix_high-nwidth,0), jx_rel=0;
8319            jx1<IMIN(ix_low+nwidth,width-1);
8320            jx1++,jx_rel++)
8321         {
8322           coeff_x[jx_rel] = ham_sinc((double)(x-jx1),2*nwidth);
8323           coeff_x_sum += coeff_x[jx_rel];
8324         }
8325       for (jy1=IMAX(iy_high-nwidth,0), jy_rel=0;
8326            jy1<IMIN(iy_low+nwidth,height-1);
8327            jy1++,jy_rel++)
8328         {
8329           coeff_y[jy_rel] = ham_sinc((double)(y-jy1),2*nwidth);
8330           coeff_y_sum += coeff_y[jy_rel];
8331         }
8332       for (jz1=IMAX(iz_high-nwidth,0), jz_rel=0;
8333            jz1<IMIN(iz_low+nwidth,depth-1);
8334            jz1++,jz_rel++)
8335         {
8336           coeff_z[jz_rel] = ham_sinc((double)(z-jz1),2*nwidth);
8337           coeff_z_sum += coeff_z[jz_rel];
8338         }
8339 
8340       for(sum_z=0., jz1=IMAX(iz_high-nwidth,0), jz_rel = 0;
8341           jz1 < IMIN(iz_low+nwidth,depth-1);
8342           jz1++, jz_rel++)
8343         {
8344 
8345           for(sum_y=0., jy1=IMAX(iy_high-nwidth,0), jy_rel = 0;
8346               jy1 < IMIN(iy_low+nwidth,height-1);
8347               jy1++, jy_rel++)
8348             {
8349               for(sum_x=0., jx1=IMAX(ix_high-nwidth,0), jx_rel = 0;
8350                   jx1 < IMIN(ix_low+nwidth,width-1);
8351                   jx1++, jx_rel++)
8352                 {
8353 
8354                   switch(mri->type)
8355                     {
8356                     case MRI_UCHAR:
8357                       sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8358                         * (double)MRIvox(mri,jx1,jy1,jz1);
8359                       break;
8360                     case MRI_SHORT:
8361                       sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8362                         * (double)MRISvox(mri,jx1,jy1,jz1);
8363                       break;
8364                     case MRI_INT:
8365                       sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8366                         * (double)MRIIvox(mri,jx1,jy1,jz1);
8367                       break;
8368                     case MRI_LONG:
8369                       sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8370                         * (double)MRILvox(mri,jx1,jy1,jz1);
8371                       break;
8372                     case MRI_FLOAT:
8373                       sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8374                         * (double)MRIFvox(mri,jx1,jy1,jz1);
8375                       break;
8376                     default:
8377                       ErrorReturn(ERROR_UNSUPPORTED,
8378                                   (ERROR_UNSUPPORTED,
8379                                    "MRIsincSampleVolume: unsupported type %d",
8380                                    mri->type)) ;
8381                       break;
8382                     }
8383                 }
8384               sum_y += sum_x * (coeff_y[jy_rel]/coeff_y_sum);
8385             }
8386           sum_z += sum_y * (coeff_z[jz_rel]/coeff_z_sum);
8387         }
8388       if((mri->type == MRI_UCHAR || mri->type == MRI_SHORT) && sum_z<0.0)
8389         *pval = 0.0;
8390       else if(mri->type == MRI_UCHAR && sum_z >255.0)
8391         *pval = 255.0;
8392       else if(mri->type == MRI_SHORT && sum_z > 65535.0)
8393         *pval = 65535.0;
8394       else
8395         *pval = sum_z;
8396     }
8397   else
8398     *pval = 0.0;
8399 
8400   return(NO_ERROR);
8401 }
8402 /*-----------------------------------------------------------------
8403   MRIindexNotInVolume() - determines whether a col, row, slice point is
8404   in the mri volume. If it is unambiguously in the volume, then 0
8405   is returned. If it is within 0.5 of the edge of the volume, -1
8406   is returned. Otherwise 1 is returned. Flagging the case where
8407   the point is within 0.5 of the edge can be used for assigning
8408   a nearest neighbor when the point is outside but close to the
8409   volume. In this case the index of the nearest neighbor can safely
8410   be computed as the nearest integer to col, row, and slice.
8411   -----------------------------------------------------------------*/
8412 int MRIindexNotInVolume(MRI *mri, Real col, Real row, Real slice)
8413 {
8414   float nicol, nirow, nislice;
8415 
8416   /* unambiguously in the volume */
8417   if(col   >= 0 && col   <= mri->width-1  &&
8418      row   >= 0 && row   <= mri->height-1 &&
8419      slice >= 0 && slice <= mri->depth-1  )
8420     return(0);
8421 
8422   /* within 0.5 of the edge of the volume */
8423   nicol   = rint(col);
8424   nirow   = rint(row);
8425   nislice = rint(slice);
8426   if(nicol   >= 0 && nicol   < mri->width  &&
8427      nirow   >= 0 && nirow   < mri->height &&
8428      nislice >= 0 && nislice < mri->depth  )
8429     return(-1);
8430 
8431   /* unambiguously NOT in the volume */
8432   return(1);
8433 
8434 }
8435 /*-----------------------------------------------------
8436   Parameters:
8437 
8438   Returns value:
8439 
8440   Description
8441   Interpolate the volume directional derivative using
8442   trilinear interpolation.
8443   ------------------------------------------------------*/
8444 float
8445 MRIsampleCardinalDerivative(MRI *mri, int x, int y, int z,
8446                             int xk, int yk, int zk)
8447 {
8448   float d ;
8449 
8450   if (xk)
8451     d = MRIsampleXDerivative(mri, x, y, z, xk) ;
8452   else if (yk)
8453     d = MRIsampleYDerivative(mri, x, y, z, yk) ;
8454   else
8455     d = MRIsampleZDerivative(mri, x, y, z, zk) ;
8456   return(d) ;
8457 }
8458 /*-----------------------------------------------------
8459   Parameters:
8460 
8461   Returns value:
8462 
8463   Description
8464   Interpolate the volume directional derivative using
8465   trilinear interpolation.
8466   ------------------------------------------------------*/
8467 float
8468 MRIsampleXDerivative(MRI *mri, int x, int y, int z, int dir)
8469 {
8470   float dx ;
8471   int   yk, zk, xi, yi, zi, nvox ;
8472 
8473   dx = 0.0 ;
8474 
8475   xi = mri->xi[x+dir] ;
8476   for (nvox = 0, zk = -1 ; zk <= 1 ; zk++)
8477     {
8478       zi = mri->zi[z+zk] ;
8479       for (yk = -1 ; yk <= 1 ; yk++)
8480         {
8481           yi = mri->yi[y+yk] ;
8482           dx += dir*MRIvox(mri, xi, yi, zi) ;  /* x+dir */
8483           dx -= dir*MRIvox(mri, x, yi, zi) ;   /* - x */
8484           nvox += 2 ;
8485         }
8486     }
8487   dx /= ((float)nvox*mri->xsize) ;
8488   return(dx) ;
8489 }
8490 /*-----------------------------------------------------
8491   Parameters:
8492 
8493   Returns value:
8494 
8495   Description
8496   Interpolate the volume directional derivative using
8497   trilinear interpolation.
8498   ------------------------------------------------------*/
8499 float
8500 MRIsampleYDerivative(MRI *mri, int x, int y, int z, int dir)
8501 {
8502   float dy ;
8503   int   xk, zk, xi, yi, zi, nvox ;
8504 
8505   dy = 0.0 ;
8506 
8507   yi = mri->yi[y+dir] ;
8508   for (nvox = 0, zk = -1 ; zk <= 1 ; zk++)
8509     {
8510       zi = mri->zi[z+zk] ;
8511       for (xk = -1 ; xk <= 1 ; xk++)
8512         {
8513           xi = mri->xi[x+xk] ;
8514           dy += dir*MRIvox(mri, xi, yi, zi) ;  /* x+dir */
8515           dy -= dir*MRIvox(mri, x, yi, zi) ;   /* - x */
8516           nvox += 2 ;
8517         }
8518     }
8519   dy /= ((float)nvox*mri->ysize) ;
8520   return(dy) ;
8521 }
8522 /*-----------------------------------------------------
8523   Parameters:
8524 
8525   Returns value:
8526 
8527   Description
8528   Interpolate the volume directional derivative using
8529   trilinear interpolation.
8530   ------------------------------------------------------*/
8531 float
8532 MRIsampleZDerivative(MRI *mri, int x, int y, int z, int dir)
8533 {
8534   float dz ;
8535   int   xk, yk, xi, yi, zi, nvox ;
8536 
8537   dz = 0.0 ;
8538 
8539   zi = mri->zi[z+dir] ;
8540   for (nvox = 0, xk = -1 ; xk <= 1 ; xk++)
8541     {
8542       xi = mri->xi[x+xk] ;
8543       for (yk = -1 ; yk <= 1 ; yk++)
8544         {
8545           yi = mri->yi[y+yk] ;
8546           dz += dir*MRIvox(mri, xi, yi, zi) ;  /* x+dir */
8547           dz -= dir*MRIvox(mri, x, yi, zi) ;   /* - x */
8548           nvox += 2 ;
8549         }
8550     }
8551   dz /= ((float)nvox*mri->zsize) ;
8552   return(dz) ;
8553 }
8554 int
8555 MRIsampleVolumeDirectionScale(MRI *mri, Real x, Real y, Real z,
8556                               Real dx, Real dy, Real dz, Real *pmag,
8557                               double sigma)
8558 {
8559   int  width, height, depth ;
8560   Real xp1, xm1, yp1, ym1, zp1, zm1, len ;
8561   Real dist, val, k, ktotal, step_size, total_val ;
8562   int  n ;
8563 
8564   width = mri->width ; height = mri->height ; depth = mri->depth ;
8565   if (x >= width)
8566     x = width - 1.0 ;
8567   if (y >= height)
8568     y = height - 1.0 ;
8569   if (z >= depth)
8570     z = depth - 1.0 ;
8571   if (x < 0.0)
8572     x = 0.0 ;
8573   if (y < 0.0)
8574     y = 0.0 ;
8575   if (z < 0.0)
8576     z = 0.0 ;
8577 
8578   step_size = MAX(.5,sigma/2) ;
8579   for (total_val = ktotal = 0.0,n = 0, len = 0.0, dist = step_size ;
8580        dist <= MAX(2*sigma,step_size);
8581        dist += step_size, n++)
8582     {
8583       if (FZERO(sigma))
8584         k = 1.0 ;
8585       else
8586         k = exp(-dist*dist/(2*sigma*sigma)) ;
8587       ktotal += k ;
8588       len += dist ;
8589       xp1 = x + dist*dx ; yp1 = y + dist*dy ; zp1 = z + dist*dz ;
8590       MRIsampleVolume(mri, xp1, yp1, zp1, &val) ;
8591       total_val += k*val ;
8592 
8593       xm1 = x - dist*dx ; ym1 = y - dist*dy ; zm1 = z - dist*dz ;
8594       MRIsampleVolume(mri, xm1, ym1, zm1, &val) ;
8595       total_val += k*val ;
8596       if (FZERO(step_size))
8597         break ;
8598     }
8599   total_val /= (double)2.0*ktotal ;
8600 
8601   *pmag = total_val ;
8602   return(NO_ERROR) ;
8603 }
8604 
8605 int
8606 MRIsampleVolumeDerivativeScale(MRI *mri, Real x, Real y, Real z, Real dx,
8607                                Real dy, Real dz, Real *pmag, double sigma)
8608 {
8609   int  width, height, depth ;
8610   Real xp1, xm1, yp1, ym1, zp1, zm1, vp1, vm1, len ;
8611   Real dist, val, k, ktotal, step_size ;
8612   int  n ;
8613 
8614   width = mri->width ; height = mri->height ; depth = mri->depth ;
8615   if (x >= width)
8616     x = width - 1.0 ;
8617   if (y >= height)
8618     y = height - 1.0 ;
8619   if (z >= depth)
8620     z = depth - 1.0 ;
8621   if (x < 0.0)
8622     x = 0.0 ;
8623   if (y < 0.0)
8624     y = 0.0 ;
8625   if (z < 0.0)
8626     z = 0.0 ;
8627 
8628   step_size = MAX(.5,sigma/2) ;
8629   for (ktotal = 0.0,n = 0, len = vp1 = vm1 = 0.0, dist = step_size ;
8630        dist <= MAX(2*sigma,step_size);
8631        dist += step_size, n++)
8632     {
8633       if (FZERO(sigma))
8634         k = 1.0 ;
8635       else
8636         k = exp(-dist*dist/(2*sigma*sigma)) ;
8637       ktotal += k ;
8638       len += dist ;
8639       xp1 = x + dist*dx ; yp1 = y + dist*dy ; zp1 = z + dist*dz ;
8640       MRIsampleVolume(mri, xp1, yp1, zp1, &val) ;
8641       vp1 += k*val ;
8642 
8643       xm1 = x - dist*dx ; ym1 = y - dist*dy ; zm1 = z - dist*dz ;
8644       MRIsampleVolume(mri, xm1, ym1, zm1, &val) ;
8645       vm1 += k*val ;
8646       if (FZERO(step_size))
8647         break ;
8648     }
8649   vm1 /= (double)ktotal ; vp1 /= (double)ktotal ; len /= (double)ktotal ;
8650 
8651   *pmag = (vp1-vm1) / (2.0*len) ;
8652   return(NO_ERROR) ;
8653 }
8654 /*-----------------------------------------------------
8655   Parameters:
8656 
8657   Returns value:
8658 
8659   Description
8660   Interpolate the volume directional derivative using
8661   trilinear interpolation.
8662   ------------------------------------------------------*/
8663 int
8664 MRIsampleVolumeDerivative(MRI *mri, Real x, Real y, Real z,
8665                           Real dx, Real dy, Real dz, Real *pmag)
8666 {
8667   int  width, height, depth ;
8668   Real xp1, xm1, yp1, ym1, zp1, zm1, vp1, vm1, len ;
8669 
8670   width = mri->width ; height = mri->height ; depth = mri->depth ;
8671   if (x >= width)
8672     x = width - 1.0 ;
8673   if (y >= height)
8674     y = height - 1.0 ;
8675   if (z >= depth)
8676     z = depth - 1.0 ;
8677   if (x < 0.0)
8678     x = 0.0 ;
8679   if (y < 0.0)
8680     y = 0.0 ;
8681   if (z < 0.0)
8682     z = 0.0 ;
8683 #if 1
8684   {
8685     Real dist, val ;
8686     int  n ;
8687 
8688     for (n = 0, len = vp1 = vm1 = 0.0, dist = .5 ; dist <= 2 ;
8689          dist += 0.5, n++)
8690       {
8691         len += dist ;
8692         xp1 = x + dist*dx ; yp1 = y + dist*dy ; zp1 = z + dist*dz ;
8693         MRIsampleVolume(mri, xp1, yp1, zp1, &val) ;
8694         vp1 += val ;
8695 
8696         xm1 = x - dist*dx ; ym1 = y - dist*dy ; zm1 = z - dist*dz ;
8697         MRIsampleVolume(mri, xm1, ym1, zm1, &val) ;
8698         vm1 += val ;
8699       }
8700     vm1 /= (double)n ; vp1 /= (double)n ; len /= (double)n ;
8701   }
8702 #else
8703   xp1 = x + dx ; xm1 = x - dx ;
8704   yp1 = y + dy ; ym1 = y - dy ;
8705   zp1 = z + dz ; zm1 = z - dz ;
8706   len = sqrt(dx*dx+dy*dy+dz*dz) ;
8707   MRIsampleVolume(mri, xp1, yp1, zp1, &vp1) ;
8708   MRIsampleVolume(mri, xm1, ym1, zm1, &vm1) ;
8709 #endif
8710 
8711   *pmag = (vp1-vm1) / (2.0*len) ;
8712   return(NO_ERROR) ;
8713 }
8714 /*-----------------------------------------------------
8715   Parameters:
8716 
8717   Returns value:
8718 
8719   Description
8720   Interpolate the volume gradient to cubic voxels.
8721   ------------------------------------------------------*/
8722 int
8723 MRIsampleVolumeGradient(MRI *mri, Real x, Real y, Real z,
8724                         Real *pdx, Real *pdy, Real *pdz)
8725 {
8726   int  width, height, depth ;
8727   Real xp1, xm1, yp1, ym1, zp1, zm1 ;
8728 
8729   width = mri->width ; height = mri->height ; depth = mri->depth ;
8730   if (x >= width)
8731     x = width - 1.0 ;
8732   if (y >= height)
8733     y = height - 1.0 ;
8734   if (z >= depth)
8735     z = depth - 1.0 ;
8736   if (x < 0.0)
8737     x = 0.0 ;
8738   if (y < 0.0)
8739     y = 0.0 ;
8740   if (z < 0.0)
8741     z = 0.0 ;
8742   MRIsampleVolume(mri, x+1.0, y, z, &xp1) ;
8743   MRIsampleVolume(mri, x-1.0, y, z, &xm1) ;
8744 
8745   MRIsampleVolume(mri, x, y+1.0, z, &yp1) ;
8746   MRIsampleVolume(mri, x, y-1.0, z, &ym1) ;
8747 
8748   MRIsampleVolume(mri, x, y, z+1.0, &zp1) ;
8749   MRIsampleVolume(mri, x, y, z-1.0, &zm1) ;
8750 
8751   *pdx = (xp1-xm1)/(2.0*mri->xsize) ;
8752   *pdy = (yp1-ym1)/(2.0*mri->ysize) ;
8753   *pdz = (zp1-zm1)/(2.0*mri->zsize) ;
8754   return(NO_ERROR) ;
8755 }
8756 /*-----------------------------------------------------
8757   Parameters:
8758 
8759   Returns value:
8760 
8761   Description
8762   Interpolate the volume gradient to cubic voxels.
8763   ------------------------------------------------------*/
8764 int
8765 MRIsampleVolumeGradientFrame(MRI *mri, Real x, Real y, Real z,
8766                              Real *pdx, Real *pdy, Real *pdz, int frame)
8767 {
8768   int  width, height, depth ;
8769   Real xp1, xm1, yp1, ym1, zp1, zm1 ;
8770 
8771   width = mri->width ; height = mri->height ; depth = mri->depth ;
8772   if (x >= width)
8773     x = width - 1.0 ;
8774   if (y >= height)
8775     y = height - 1.0 ;
8776   if (z >= depth)
8777     z = depth - 1.0 ;
8778   if (x < 0.0)
8779     x = 0.0 ;
8780   if (y < 0.0)
8781     y = 0.0 ;
8782   if (z < 0.0)
8783     z = 0.0 ;
8784   if (frame >= mri->nframes)
8785     frame = mri->nframes-1 ;
8786   if (frame < 0)
8787     frame = 0 ;
8788 
8789   MRIsampleVolumeFrame(mri, x+1.0, y, z, frame, &xp1) ;
8790   MRIsampleVolumeFrame(mri, x-1.0, y, z, frame, &xm1) ;
8791 
8792   MRIsampleVolumeFrame(mri, x, y+1.0, z, frame, &yp1) ;
8793   MRIsampleVolumeFrame(mri, x, y-1.0, z, frame, &ym1) ;
8794 
8795   MRIsampleVolumeFrame(mri, x, y, z+1.0, frame, &zp1) ;
8796   MRIsampleVolumeFrame(mri, x, y, z-1.0, frame, &zm1) ;
8797 
8798   *pdx = (xp1-xm1)/(2.0*mri->xsize) ;
8799   *pdy = (yp1-ym1)/(2.0*mri->ysize) ;
8800   *pdz = (zp1-zm1)/(2.0*mri->zsize) ;
8801   return(NO_ERROR) ;
8802 }
8803 /*-----------------------------------------------------
8804   Parameters:
8805 
8806   Returns value:
8807 
8808   Description
8809   ------------------------------------------------------*/
8810 int
8811 MRIneighborsOn(MRI *mri, int x0, int y0, int z0, int min_val)
8812 {
8813   int   nbrs = 0 ;
8814 
8815   if (MRIvox(mri,mri->xi[x0-1],y0,z0) >= min_val)
8816     nbrs++ ;
8817   if (MRIvox(mri,mri->xi[x0+1],y0,z0) >= min_val)
8818     nbrs++ ;
8819   if (MRIvox(mri,x0,mri->yi[y0+1],z0) >= min_val)
8820     nbrs++ ;
8821   if (MRIvox(mri,x0,mri->yi[y0-1],z0) >= min_val)
8822     nbrs++ ;
8823   if (MRIvox(mri,x0,y0,mri->zi[z0+1]) >= min_val)
8824     nbrs++ ;
8825   if (MRIvox(mri,x0,y0,mri->zi[z0-1]) >= min_val)
8826     nbrs++ ;
8827   return(nbrs) ;
8828 }
8829 /*-----------------------------------------------------
8830   Parameters:
8831 
8832   Returns value:
8833 
8834   Description
8835   ------------------------------------------------------*/
8836 int
8837 MRIneighborsOn3x3(MRI *mri, int x, int y, int z, int min_val)
8838 {
8839   int   xk, yk, zk, xi, yi, zi, nbrs ;
8840 
8841   for (nbrs = 0, zk = -1 ; zk <= 1 ; zk++)
8842     {
8843       zi = mri->zi[z+zk] ;
8844       for (yk = -1 ; yk <= 1 ; yk++)
8845         {
8846           yi = mri->yi[y+yk] ;
8847           for (xk = -1 ; xk <= 1 ; xk++)
8848             {
8849               xi = mri->xi[x+xk] ;
8850               if (!zk && !yk && !xk)
8851                 continue ;
8852               if (MRIvox(mri, xi, yi, zi) > min_val)
8853                 nbrs++ ;
8854             }
8855         }
8856     }
8857   return(nbrs) ;
8858 }
8859 /*-----------------------------------------------------
8860   Parameters:
8861 
8862   Returns value:
8863 
8864   Description
8865   ------------------------------------------------------*/
8866 int
8867 MRIneighborsInWindow(MRI *mri, int x, int y, int z, int wsize, int val)
8868 {
8869   int   xk, yk, zk, xi, yi, zi, nbrs, whalf ;
8870 
8871   whalf = (wsize-1)/2 ;
8872 
8873   for (nbrs = 0, zk = -whalf ; zk <= whalf ; zk++)
8874     {
8875       zi = mri->zi[z+zk] ;
8876       for (yk = -whalf ; yk <= whalf ; yk++)
8877         {
8878           yi = mri->yi[y+yk] ;
8879           for (xk = -whalf ; xk <= whalf ; xk++)
8880             {
8881               xi = mri->xi[x+xk] ;
8882               if (!zk && !yk && !xk)
8883                 continue ;
8884               if (MRIvox(mri, xi, yi, zi) == val)
8885                 nbrs++ ;
8886             }
8887         }
8888     }
8889   return(nbrs) ;
8890 }
8891 /*-----------------------------------------------------
8892   Parameters:
8893 
8894   Returns value:
8895 
8896   Description
8897   ------------------------------------------------------*/
8898 int
8899 MRIneighbors(MRI *mri, int x0, int y0, int z0, int val)
8900 {
8901   int   nbrs = 0 ;
8902 
8903   if (nint(MRIgetVoxVal(mri,mri->xi[x0-1],y0,z0,0)) == val)
8904     nbrs++ ;
8905   if (nint(MRIgetVoxVal(mri,mri->xi[x0+1],y0,z0,0)) == val)
8906     nbrs++ ;
8907   if (nint(MRIgetVoxVal(mri,x0,mri->yi[y0+1],z0,0)) == val)
8908     nbrs++ ;
8909   if (nint(MRIgetVoxVal(mri,x0,mri->yi[y0-1],z0,0)) == val)
8910     nbrs++ ;
8911   if (nint(MRIgetVoxVal(mri,x0,y0,mri->zi[z0+1],0)) == val)
8912     nbrs++ ;
8913   if (nint(MRIgetVoxVal(mri,x0,y0,mri->zi[z0-1],0)) == val)
8914     nbrs++ ;
8915   return(nbrs) ;
8916 }
8917 /*-----------------------------------------------------
8918   Parameters:
8919 
8920   Returns value:
8921 
8922   Description
8923   ------------------------------------------------------*/
8924 int
8925 MRIneighbors3x3(MRI *mri, int x, int y, int z, int val)
8926 {
8927   int   xk, yk, zk, xi, yi, zi, nbrs ;
8928 
8929   for (nbrs = 0, zk = -1 ; zk <= 1 ; zk++)
8930     {
8931       zi = mri->zi[z+zk] ;
8932       for (yk = -1 ; yk <= 1 ; yk++)
8933         {
8934           yi = mri->yi[y+yk] ;
8935           for (xk = -1 ; xk <= 1 ; xk++)
8936             {
8937               xi = mri->xi[x+xk] ;
8938               if (!zk && !yk && !xk)
8939                 continue ;
8940               if (MRIvox(mri, xi, yi, zi) == val)
8941                 nbrs++ ;
8942             }
8943         }
8944     }
8945   return(nbrs) ;
8946 }
8947 /*-----------------------------------------------------
8948   ------------------------------------------------------*/
8949 int
8950 MRIneighborsOff(MRI *mri, int x0, int y0, int z0, int min_val)
8951 {
8952   int   nbrs = 0 ;
8953 
8954   if (MRIvox(mri,x0-1,y0,z0) < min_val)
8955     nbrs++ ;
8956   if (MRIvox(mri,x0+1,y0,z0) < min_val)
8957     nbrs++ ;
8958   if (MRIvox(mri,x0,y0+1,z0) < min_val)
8959     nbrs++ ;
8960   if (MRIvox(mri,x0,y0-1,z0) < min_val)
8961     nbrs++ ;
8962   if (MRIvox(mri,x0,y0,z0+1) < min_val)
8963     nbrs++ ;
8964   if (MRIvox(mri,x0,y0,z0-1) < min_val)
8965     nbrs++ ;
8966   return(nbrs) ;
8967 }
8968 /*-----------------------------------------------------
8969   ------------------------------------------------------*/
8970 int
8971 MRIneighborsOff3x3(MRI *mri, int x, int y, int z, int min_val)
8972 {
8973   int   xk, yk, zk, xi, yi, zi, nbrs ;
8974 
8975   for (nbrs = 0, zk = -1 ; zk <= 1 ; zk++)
8976     {
8977       zi = mri->zi[z+zk] ;
8978       for (yk = -1 ; yk <= 1 ; yk++)
8979         {
8980           yi = mri->yi[y+yk] ;
8981           for (xk = -1 ; xk <= 1 ; xk++)
8982             {
8983               xi = mri->xi[x+xk] ;
8984               if (!zk && !yk && !xk)
8985                 continue ;
8986               if (MRIvox(mri, xi, yi, zi) < min_val)
8987                 nbrs++ ;
8988             }
8989         }
8990     }
8991   return(nbrs) ;
8992 }
8993 /*-----------------------------------------------------
8994   Perform an linear coordinate transformation x' = Ax on
8995   the MRI image mri_src into mri_dst
8996   ------------------------------------------------------*/
8997 MRI *
8998 MRIinverseLinearTransform(MRI *mri_src, MRI *mri_dst, MATRIX *mA)
8999 {
9000   MATRIX  *m_inv ;
9001 
9002   m_inv = MatrixInverse(mA, NULL) ;
9003   if   (!m_inv)
9004     ErrorReturn
9005       (NULL,
9006        (ERROR_BADPARM,
9007         "MRIinverseLinearTransform: xform is singular!")) ;
9008   fprintf
9009     (stderr,
9010      "applying the vox-to-vox linear transform (calculated inverse)\n");
9011   MatrixPrint(stderr, m_inv);
9012   mri_dst = MRIlinearTransform(mri_src, mri_dst, m_inv) ;
9013   MatrixFree(&m_inv) ;
9014   return(mri_dst) ;
9015 }
9016 /*-----------------------------------------------------
9017   Convert a transform from RAS to voxel coordinates, then apply
9018   it to an MRI.
9019   ------------------------------------------------------*/
9020 MRI *
9021 MRIapplyRASlinearTransform(MRI *mri_src, MRI *mri_dst, MATRIX *m_ras_xform)
9022 {
9023   MATRIX   *m_voxel_xform ;
9024 
9025   m_voxel_xform = MRIrasXformToVoxelXform(mri_src, mri_dst, m_ras_xform, NULL);
9026   fprintf(stderr, "applying the vox to vox linear transform\n");
9027   MatrixPrint(stderr, m_voxel_xform);
9028   mri_dst = MRIlinearTransform(mri_src, mri_dst, m_voxel_xform) ;
9029   MatrixFree(&m_voxel_xform) ;
9030   return(mri_dst) ;
9031 }
9032 /*-----------------------------------------------------
9033   Convert a transform from RAS to voxel coordinates, then apply
9034   it to an MRI.
9035   ------------------------------------------------------*/
9036 MRI *
9037 MRIapplyRASlinearTransformInterp
9038 (MRI *mri_src, MRI *mri_dst, MATRIX *m_ras_xform, int interp)
9039 {
9040   MATRIX   *m_voxel_xform ;
9041 
9042   m_voxel_xform = MRIrasXformToVoxelXform(mri_src, mri_dst, m_ras_xform, NULL);
9043   fprintf(stderr, "applying the vox to vox linear transform\n");
9044   MatrixPrint(stderr, m_voxel_xform);
9045   mri_dst = MRIlinearTransformInterp(mri_src, mri_dst, m_voxel_xform, interp) ;
9046   MatrixFree(&m_voxel_xform) ;
9047   return(mri_dst) ;
9048 }
9049 /*-----------------------------------------------------
9050   Convert a transform from RAS to voxel coordinates, then apply
9051   it to an MRI.
9052   ------------------------------------------------------*/
9053 MRI *
9054 MRIapplyRASinverseLinearTransform(MRI *mri_src, MRI *mri_dst,
9055                                   MATRIX *m_ras_xform)
9056 {
9057   MATRIX   *m_voxel_xform ;
9058 
9059   m_voxel_xform = MRIrasXformToVoxelXform(mri_src, mri_dst, m_ras_xform, NULL);
9060   mri_dst = MRIinverseLinearTransform(mri_src, mri_dst, m_voxel_xform) ;
9061   MatrixFree(&m_voxel_xform) ;
9062   return(mri_dst) ;
9063 }
9064 
9065 /*-----------------------------------------------------
9066   Perform an linear coordinate transformation x' = Ax on
9067   the MRI image mri_src into mri_dst using sinc interp.
9068   ------------------------------------------------------*/
9069 MRI *
9070 MRIsincTransform(MRI *mri_src, MRI *mri_dst, MATRIX *mA, int hw)
9071 {
9072   int    y1, y2, y3, width, height, depth ;
9073   VECTOR *v_X, *v_Y ;   /* original and transformed coordinate systems */
9074   MATRIX *mAinv ;     /* inverse of mA */
9075   Real   val, x1, x2, x3 ;
9076 
9077   mAinv = MatrixInverse(mA, NULL) ;      /* will sample from dst back to src */
9078   if (!mAinv)
9079     ErrorReturn(NULL, (ERROR_BADPARM,
9080                        "MRIsincTransform: xform is singular")) ;
9081 
9082   width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth ;
9083   if (!mri_dst)
9084     mri_dst = MRIclone(mri_src, NULL) ;
9085   else
9086     MRIclear(mri_dst) ;
9087 
9088   v_X = VectorAlloc(4, MATRIX_REAL) ;  /* input (src) coordinates */
9089   v_Y = VectorAlloc(4, MATRIX_REAL) ;  /* transformed (dst) coordinates */
9090 
9091   v_Y->rptr[4][1] = 1.0f ;
9092   for (y3 = 0 ; y3 < depth ; y3++)
9093     {
9094       V3_Z(v_Y) = y3 ;
9095       for (y2 = 0 ; y2 < height ; y2++)
9096         {
9097           V3_Y(v_Y) = y2 ;
9098           for (y1 = 0 ; y1 < width ; y1++)
9099             {
9100               V3_X(v_Y) = y1 ;
9101               MatrixMultiply(mAinv, v_Y, v_X) ;
9102 
9103               x1 = V3_X(v_X) ; x2 = V3_Y(v_X) ; x3 = V3_Z(v_X) ;
9104 
9105               if (nint(y1) == 13 && nint(y2) == 10 && nint(y3) == 7)
9106                 DiagBreak() ;
9107               if (nint(x1) == 13 && nint(x2) == 10 && nint(x3) == 7)
9108                 {
9109 #if 0
9110                   fprintf
9111                     (stderr,
9112                      "(%2.1f, %2.1f, %2.1f) --> (%2.1f, %2.1f, %2.1f)\n",
9113                      (float)x1, (float)x2, (float)x3,
9114                      (float)y1, (float)y2, (float)y3) ;
9115 #endif
9116                   DiagBreak() ;
9117                 }
9118 
9119               if (x1 > -1 && x1 < width &&
9120                   x2 > -1 && x2 < height &&
9121                   x3 > -1 && x3 < depth)
9122                 {
9123                   MRIsincSampleVolume(mri_src, x1, x2, x3, hw, &val);
9124                   MRIvox(mri_dst,y1,y2,y3) = (BUFTYPE)nint(val) ;
9125                 }
9126             }
9127         }
9128     }
9129 
9130   MatrixFree(&v_X) ;
9131   MatrixFree(&mAinv) ;
9132   MatrixFree(&v_Y) ;
9133 
9134   mri_dst->ras_good_flag = 0;
9135 
9136   return(mri_dst) ;
9137 }
9138 /*-----------------------------------------------------------------
9139   MRIlinearTransform() - for historical reasons, this uses trilinear
9140   interpolation. This the operations under this function name can
9141   now (2/20/02) be found under MRIlinearTransformInterp().
9142   -----------------------------------------------------------------*/
9143 MRI *
9144 MRIlinearTransform(MRI *mri_src, MRI *mri_dst, MATRIX *mA)
9145 {
9146   mri_dst = MRIlinearTransformInterp(mri_src, mri_dst, mA, SAMPLE_TRILINEAR);
9147   return(mri_dst);
9148 }
9149 /*-------------------------------------------------------------------
9150   MRIlinearTransformInterp() Perform linear coordinate transformation
9151   x' = Ax on the MRI image mri_src into mri_dst using the specified
9152   interpolation method. A is a voxel-to-voxel transform.
9153   ------------------------------------------------------------------*/
9154 MRI *
9155 MRIlinearTransformInterp(MRI *mri_src, MRI *mri_dst, MATRIX *mA,
9156                          int InterpMethod)
9157 {
9158   int    y1, y2, y3, width, height, depth ;
9159   VECTOR *v_X, *v_Y ;   /* original and transformed coordinate systems */
9160   MATRIX *mAinv ;     /* inverse of mA */
9161   Real   val, x1, x2, x3 ;
9162 
9163   if(InterpMethod != SAMPLE_NEAREST &&
9164      InterpMethod != SAMPLE_TRILINEAR &&
9165      InterpMethod != SAMPLE_CUBIC &&
9166      InterpMethod != SAMPLE_SINC ){
9167     printf("ERROR: MRIlinearTransformInterp: unrecoginzed interpolation "
9168            "method %d\n",InterpMethod);
9169   }
9170 
9171   mAinv = MatrixInverse(mA, NULL) ;      /* will sample from dst back to src */
9172   if (!mAinv)
9173     ErrorReturn(NULL, (ERROR_BADPARM,
9174                        "MRIlinearTransform: xform is singular")) ;
9175 
9176   if (!mri_dst)
9177     mri_dst = MRIclone(mri_src, NULL) ;
9178   else
9179     MRIclear(mri_dst) ;
9180 
9181   width = mri_dst->width ; height = mri_dst->height ; depth = mri_dst->depth ;
9182   v_X = VectorAlloc(4, MATRIX_REAL) ;  /* input (src) coordinates */
9183   v_Y = VectorAlloc(4, MATRIX_REAL) ;  /* transformed (dst) coordinates */
9184 
9185   if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
9186     printf("MRIlinearTransformInterp: Applying transform\n");
9187 
9188   v_Y->rptr[4][1] = 1.0f ;
9189   for (y3 = 0 ; y3 < depth ; y3++)
9190     {
9191       V3_Z(v_Y) = y3 ;
9192       for (y2 = 0 ; y2 < height ; y2++)
9193         {
9194           V3_Y(v_Y) = y2 ;
9195           for (y1 = 0 ; y1 < width ; y1++)
9196             {
9197               V3_X(v_Y) = y1 ;
9198               MatrixMultiply(mAinv, v_Y, v_X) ;
9199 
9200               x1 = V3_X(v_X) ; x2 = V3_Y(v_X) ; x3 = V3_Z(v_X) ;
9201 
9202               if (nint(y1) == 13 && nint(y2) == 10 && nint(y3) == 7)
9203                 DiagBreak() ;
9204               if (nint(x1) == Gx && nint(x2) == Gy && nint(x3) == Gz)
9205                 {
9206 #if 0
9207                   fprintf
9208                     (stderr,
9209                      "(%2.1f, %2.1f, %2.1f) --> (%2.1f, %2.1f, %2.1f)\n",
9210                      (float)x1, (float)x2, (float)x3,
9211                      (float)y1, (float)y2, (float)y3) ;
9212 #endif
9213                   DiagBreak() ;
9214                 }
9215 
9216               //MRIsampleVolume(mri_src, x1, x2, x3, &val);
9217               MRIsampleVolumeType(mri_src, x1, x2, x3, &val, InterpMethod);
9218               switch (mri_dst->type)
9219                 {
9220                 case MRI_UCHAR:
9221                   MRIvox(mri_dst,y1,y2,y3) = (BUFTYPE)nint(val) ;
9222                   break ;
9223                 case MRI_SHORT:
9224                   MRISvox(mri_dst,y1,y2,y3) = (short)nint(val) ;
9225                   break ;
9226                 case MRI_FLOAT:
9227                   MRIFvox(mri_dst,y1,y2,y3) = (float)(val) ;
9228                   break ;
9229                 case MRI_INT:
9230                   MRIIvox(mri_dst,y1,y2,y3) = nint(val) ;
9231                   break ;
9232                 default:
9233                   ErrorReturn(NULL,
9234                               (ERROR_UNSUPPORTED,
9235                                "MRIlinearTransform: unsupported dst type %d",
9236                                mri_dst->type)) ;
9237                   break ;
9238                 }
9239             }
9240         }
9241     }
9242 
9243   MatrixFree(&v_X) ;
9244   MatrixFree(&mAinv) ;
9245   MatrixFree(&v_Y) ;
9246 
9247   mri_dst->ras_good_flag = 1;
9248 
9249   if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
9250     {
9251       printf("MRIlinearTransform: done\n");
9252       printf("mri_dst:\n");
9253       printf(" vox res: %g %g %g\n",
9254              mri_dst->xsize,mri_dst->ysize,mri_dst->zsize);
9255       printf(" vox dim: %d %d %d\n",
9256              mri_dst->width,mri_dst->height,mri_dst->depth);
9257     }
9258 
9259   return(mri_dst) ;
9260 }
9261 MRI *
9262 MRIconcatenateFrames(MRI *mri_frame1, MRI *mri_frame2, MRI *mri_dst)
9263 {
9264   int       width, height, depth, x, y, z ;
9265   BUFTYPE   *pf1, *pf2, *pdst1, *pdst2 ;
9266 
9267   if (mri_frame1->type != MRI_UCHAR || mri_frame1->type != MRI_UCHAR)
9268     ErrorReturn(NULL,
9269                 (ERROR_UNSUPPORTED,"MRIconcatenateFrames: src must be UCHAR"));
9270 
9271   width = mri_frame1->width ;
9272   height = mri_frame1->height ;
9273   depth = mri_frame1->depth ;
9274   if (mri_dst == NULL)
9275     {
9276       mri_dst = MRIallocSequence(width, height, depth, mri_frame1->type, 2) ;
9277       MRIcopyHeader(mri_frame1, mri_dst) ;
9278     }
9279   if (!mri_dst)
9280     ErrorExit(ERROR_NOMEMORY, "MRIconcatenateFrames: could not alloc dst") ;
9281 
9282 
9283   for (z = 0 ; z < depth ; z++)
9284     {
9285       for (y = 0 ; y < height ; y++)
9286         {
9287           pdst1 = &MRIvox(mri_dst, 0, y, z) ;
9288           pdst2 = &MRIseq_vox(mri_dst, 0, y, z, 1) ;
9289           pf1 = &MRIvox(mri_frame1, 0, y, z) ;
9290           pf2 = &MRIvox(mri_frame2, 0, y, z) ;
9291           for (x = 0 ; x < width ; x++)
9292             {
9293               *pdst1++ = *pf1++ ;
9294               *pdst2++ = *pf2++ ;
9295             }
9296         }
9297     }
9298   return(mri_dst) ;
9299 }
9300 /*-----------------------------------------------------
9301   ------------------------------------------------------*/
9302 MRI *
9303 MRIcopyFrame(MRI *mri_src, MRI *mri_dst, int src_frame, int dst_frame)
9304 {
9305   int       width, height, depth, y, z, bytes ;
9306   BUFTYPE   *psrc, *pdst ;
9307 
9308   width = mri_src->width ;
9309   height = mri_src->height ;
9310   depth = mri_src->depth ;
9311 
9312   if (!mri_dst)
9313     mri_dst =
9314       MRIallocSequence(width, height, depth, mri_src->type, dst_frame+1) ;
9315   if (!mri_dst)
9316     ErrorExit(ERROR_NOMEMORY, "MRIcopyFrame: could not alloc dst") ;
9317 
9318   if (mri_src->type != mri_dst->type)
9319     ErrorReturn(NULL,(ERROR_UNSUPPORTED,
9320                       "MRIcopyFrame: src and dst must be same type"));
9321   if (dst_frame >= mri_dst->nframes)
9322     ErrorReturn
9323       (NULL,
9324        (ERROR_BADPARM,
9325         "MRIcopyFrame: dst frame #%d out of range (nframes=%d)\n",
9326         dst_frame, mri_dst->nframes)) ;
9327   MRIcopyHeader(mri_src, mri_dst) ;
9328 
9329   switch (mri_src->type)
9330     {
9331     case MRI_UCHAR:
9332       bytes = sizeof(unsigned char) ;
9333       break ;
9334     case MRI_SHORT:
9335       bytes = sizeof(short) ;
9336       break ;
9337     case MRI_INT:
9338       bytes = sizeof(int) ;
9339       break ;
9340     case MRI_FLOAT:
9341       bytes = sizeof(float) ;
9342       break ;
9343     default:
9344       ErrorReturn(NULL, (ERROR_BADPARM,
9345                          "MRIcopyFrame: unsupported src format %d",
9346                          mri_src->type));
9347       break ;
9348     }
9349   bytes *= width ;
9350   for (z = 0 ; z < depth ; z++)
9351     {
9352       for (y = 0 ; y < height ; y++)
9353         {
9354           switch (mri_src->type)
9355             {
9356             default:  /* already handled above */
9357             case MRI_UCHAR:
9358               psrc = &MRIseq_vox(mri_src, 0, y, z, src_frame) ;
9359               pdst = &MRIseq_vox(mri_dst, 0, y, z, dst_frame) ;
9360               break ;
9361             case MRI_SHORT:
9362               psrc = (BUFTYPE *)&MRISseq_vox(mri_src, 0, y, z, src_frame) ;
9363               pdst = (BUFTYPE *)&MRISseq_vox(mri_dst, 0, y, z, dst_frame) ;
9364               break ;
9365             case MRI_INT:
9366               psrc = (BUFTYPE *)&MRIIseq_vox(mri_src, 0, y, z, src_frame) ;
9367               pdst = (BUFTYPE *)&MRIIseq_vox(mri_dst, 0, y, z, dst_frame) ;
9368               break ;
9369             case MRI_FLOAT:
9370               psrc = (BUFTYPE *)&MRIFseq_vox(mri_src, 0, y, z, src_frame) ;
9371               pdst = (BUFTYPE *)&MRIFseq_vox(mri_dst, 0, y, z, dst_frame) ;
9372               break ;
9373             }
9374           memmove(pdst, psrc, bytes) ;
9375         }
9376     }
9377   return(mri_dst) ;
9378 }
9379 /*-----------------------------------------------------
9380   Parameters:
9381 
9382   Returns value:
9383 
9384   Description
9385   ------------------------------------------------------*/
9386 double
9387 MRImeanFrame(MRI *mri, int frame)
9388 {
9389   int       width, height, depth, x, y, z ;
9390   double    mean ;
9391   Real      val ;
9392 
9393   width = mri->width ;
9394   height = mri->height ;
9395   depth = mri->depth ;
9396   if (mri->nframes <= frame)
9397     ErrorReturn(0.0,(ERROR_BADPARM,
9398                      "MRImeanFrame: frame %d out of bounds (%d)",
9399                      frame, mri->nframes));
9400 
9401   for (mean = 0.0, z = 0 ; z < depth ; z++)
9402     {
9403       for (y = 0 ; y < height ; y++)
9404         {
9405           for (x = 0 ; x < width ; x++)
9406             {
9407               MRIsampleVolumeType(mri, x, y, z, &val, SAMPLE_NEAREST) ;
9408               mean += (double)val ;
9409             }
9410         }
9411     }
9412   mean /= (double)(width*height*depth) ;
9413   return(mean) ;
9414 }
9415 
9416 #ifndef UCHAR_MIN
9417 #define UCHAR_MIN  0.0
9418 #endif
9419 #ifndef UCHAR_MAX
9420 #define UCHAR_MAX  255.0
9421 #endif
9422 #ifndef SHORT_MIN
9423 #define SHORT_MIN  -32768.0
9424 #endif
9425 #ifndef SHORT_MAX
9426 #define SHORT_MAX  32767.0
9427 #endif
9428 #ifndef INT_MIN
9429 #define INT_MIN    -2147483648.0
9430 #endif
9431 #ifndef INT_MAX
9432 #define INT_MAX    2147483647.0
9433 #endif
9434 #ifndef LONG_MIN
9435 #define LONG_MIN   -2147483648.0
9436 #endif
9437 #ifndef LONG_MAX
9438 #define LONG_MAX   2147483647.0
9439 #endif
9440 
9441 #define N_HIST_BINS 1000
9442 
9443 /*--------------------------------------------------------------
9444   MRISeqchangeType() - changes the data type for a 3D or 4D volume.
9445   This simply changes the volume dimensions so that it appears to be a
9446   3D volume, then calls MRIchangeType(), and then resets the
9447   dimensions to their original values. The values of the volume can be
9448   rescaled between f_low and f_high.
9449   ------------------------------------------------------------*/
9450 MRI *MRISeqchangeType(MRI *vol, int dest_type, float f_low,
9451                       float f_high, int no_scale_option_flag)
9452 {
9453   int nslices, nframes;
9454   MRI *mri;
9455 
9456   /* Change vol dimensions to make it look like a single frame */
9457   nslices = vol->depth;
9458   nframes = vol->nframes;
9459   vol->depth = nslices*nframes;
9460   vol->nframes = 1;
9461 
9462   /* Change the type */
9463   mri = MRIchangeType(vol,dest_type,f_low,f_high,no_scale_option_flag);
9464 
9465   /* Change vol dimensions back to original */
9466   vol->depth = nslices;
9467   vol->nframes = nframes;
9468 
9469   /* Check for error */
9470   if(mri == NULL) {
9471     fprintf(stderr,"ERROR: MRISeqchangeType: MRIchangeType\n");
9472     return(NULL);
9473   }
9474 
9475   /* Change mri dimensions back to original */
9476   mri->depth = nslices;
9477   mri->nframes = nframes;
9478 
9479   return(mri);
9480 }
9481 /*-----------------------------------------------------------
9482   MRIchangeType() - changes the data type of a 3D MRI volume,
9483   with optional rescaling. Use MRISeqchangeType() for 3D or
9484   4D volumes.
9485   ---------------------------------------------------------*/
9486 MRI *MRIchangeType(MRI *src, int dest_type, float f_low,
9487                    float f_high, int no_scale_option_flag)
9488 {
9489 
9490   MRI *dest = NULL;
9491   int i, j, k;
9492   float val;
9493   int no_scale_flag = FALSE;
9494   float scale, dest_min, dest_max; /* new = scale * (val - min) */
9495   float src_min, src_max;
9496   int hist_bins[N_HIST_BINS];
9497   float bin_size;
9498   int bin;
9499   int nth, n_passed;
9500 
9501   /* ----- shut the compiler up ----- */
9502   val = 0.0;
9503   dest_min = dest_max = 0.0;
9504 
9505   if(src->type == dest_type)
9506     {
9507       dest = MRIcopy(src, NULL);
9508       return(dest);
9509     }
9510 
9511   if(src->type == MRI_UCHAR &&
9512      (dest_type == MRI_SHORT ||
9513       dest_type == MRI_INT ||
9514       dest_type == MRI_LONG ||
9515       dest_type == MRI_FLOAT))
9516     no_scale_flag = TRUE;
9517   else if(src->type == MRI_SHORT &&
9518           (dest_type == MRI_INT ||
9519            dest_type == MRI_LONG ||
9520            dest_type == MRI_FLOAT))
9521     no_scale_flag = TRUE;
9522   else if(src->type == MRI_LONG &&
9523           (dest_type == MRI_INT ||
9524            dest_type == MRI_FLOAT))
9525     no_scale_flag = TRUE;
9526   else if(src->type == MRI_INT &&
9527           (dest_type == MRI_LONG ||
9528            dest_type == MRI_FLOAT))
9529     no_scale_flag = TRUE;
9530   else
9531     {
9532       MRIlimits(src, &src_min, &src_max);
9533 
9534       if(no_scale_option_flag)
9535         {
9536           if(dest_type == MRI_UCHAR &&
9537              src_min >= UCHAR_MIN &&
9538              src_max <= UCHAR_MAX)
9539             no_scale_flag = TRUE;
9540           if(dest_type == MRI_SHORT &&
9541              src_min >= SHORT_MIN &&
9542              src_max <= SHORT_MAX)
9543             no_scale_flag = TRUE;
9544           if(dest_type == MRI_INT &&
9545              src_min >= INT_MIN &&
9546              src_max <= INT_MAX)
9547             no_scale_flag = TRUE;
9548           if(dest_type == MRI_LONG &&
9549              src_min >= LONG_MIN &&
9550              src_max <= LONG_MAX)
9551             no_scale_flag = TRUE;
9552         }
9553     }
9554 
9555   if(no_scale_flag)
9556     {
9557 
9558       dest = MRIalloc(src->width, src->height, src->depth, dest_type);
9559       MRIcopyHeader(src, dest);
9560       dest->type = dest_type;
9561 
9562       for(k = 0;k < src->depth;k++)
9563         for(j = 0;j < src->height;j++)
9564           for(i = 0;i < src->width;i++)
9565             {
9566 
9567               if(src->type == MRI_UCHAR)
9568                 val = (float)MRIvox(src, i, j, k);
9569               if(src->type == MRI_SHORT)
9570                 val = (float)MRISvox(src, i, j, k);
9571               if(src->type == MRI_INT)
9572                 val = (float)MRIIvox(src, i, j, k);
9573               if(src->type == MRI_LONG)
9574                 val = (float)MRILvox(src, i, j, k);
9575               if(src->type == MRI_FLOAT)
9576                 val = (float)MRIFvox(src, i, j, k);
9577 
9578               if(dest_type == MRI_UCHAR)
9579                 MRIvox(dest, i, j, k) = (unsigned char)val;
9580               if(dest_type == MRI_SHORT)
9581                 MRISvox(dest, i, j, k) = (short)val;
9582               if(dest_type == MRI_INT)
9583                 MRIIvox(dest, i, j, k) = (int)val;
9584               if(dest_type == MRI_LONG)
9585                 MRILvox(dest, i, j, k) = (long)val;
9586               if(dest_type == MRI_FLOAT)
9587                 MRIFvox(dest, i, j, k) = (float)val;
9588             }
9589     }
9590   else
9591     {
9592       long nonzero = 0 ;
9593 
9594       /* ----- build a histogram ----- */
9595       printf("MRIchangeType: Building histogram \n");
9596       bin_size = (src_max - src_min) / (float)N_HIST_BINS;
9597 
9598       for(i = 0;i < N_HIST_BINS;i++)
9599         hist_bins[i] = 0;
9600 
9601       for(i = 0;i < src->width;i++)
9602         for(j = 0;j < src->height;j++)
9603           for(k = 0;k < src->depth;k++)
9604             {
9605 
9606               if(src->type == MRI_UCHAR)
9607                 val = (float)MRIvox(src, i, j, k);
9608               if(src->type == MRI_SHORT)
9609                 val = (float)MRISvox(src, i, j, k);
9610               if(src->type == MRI_INT)
9611                 val = (float)MRIIvox(src, i, j, k);
9612               if(src->type == MRI_LONG)
9613                 val = (float)MRILvox(src, i, j, k);
9614               if(src->type == MRI_FLOAT)
9615                 val = (float)MRIFvox(src, i, j, k);
9616 
9617               if (!DZERO(val))
9618                 nonzero++ ;
9619               bin = (int)((val - src_min) / bin_size);
9620 
9621               if(bin < 0)
9622                 bin = 0;
9623               if(bin >= N_HIST_BINS)
9624                 bin = N_HIST_BINS-1;
9625 
9626               hist_bins[bin]++;
9627 
9628             }
9629 
9630       nth = (int)(f_low * src->width * src->height * src->depth);
9631       for(n_passed = 0,bin = 0;n_passed < nth && bin < N_HIST_BINS;bin++)
9632         n_passed += hist_bins[bin];
9633       src_min = (float)bin * bin_size + src_min;
9634 
9635 #if 1  // handle mostly empty volumes
9636       nth = (int)((1.0-f_high) * nonzero);
9637 #else
9638       nth = (int)((1.0-f_high) * src->width * src->height * src->depth);
9639 #endif
9640       for(n_passed = 0,bin = N_HIST_BINS-1;n_passed < nth && bin > 0;bin--)
9641         n_passed += hist_bins[bin];
9642       src_max = (float)bin * bin_size + src_min;
9643 
9644       if(src_min >= src_max)
9645         {
9646           ErrorReturn
9647             (NULL,
9648              (ERROR_BADPARM,
9649               "MRIchangeType(): after hist: src_min = %g, "
9650               "src_max = %g (f_low = %g, f_high = %g)",
9651               src_min, src_max, f_low, f_high));
9652         }
9653 
9654       /* ----- continue ----- */
9655 
9656       if(dest_type == MRI_UCHAR)
9657         {
9658           dest_min = UCHAR_MIN;
9659           dest_max = UCHAR_MAX;
9660         }
9661       if(dest_type == MRI_SHORT)
9662         {
9663           dest_min = SHORT_MIN;
9664           dest_max = SHORT_MAX;
9665         }
9666       if(dest_type == MRI_INT)
9667         {
9668           dest_min = INT_MIN;
9669           dest_max = INT_MAX;
9670         }
9671       if(dest_type == MRI_LONG)
9672         {
9673           dest_min = LONG_MIN;
9674           dest_max = LONG_MAX;
9675         }
9676 
9677       scale = (dest_max - dest_min) / (src_max - src_min);
9678 
9679       dest = MRIalloc(src->width, src->height, src->depth, dest_type);
9680       MRIcopyHeader(src, dest);
9681       dest->type = dest_type;
9682 
9683       for(i = 0;i < src->width;i++)
9684         for(j = 0;j < src->height;j++)
9685           for(k = 0;k < src->depth;k++)
9686             {
9687 
9688               if(src->type == MRI_SHORT)
9689                 val = MRISvox(src, i, j, k);
9690               if(src->type == MRI_INT)
9691                 val = MRIIvox(src, i, j, k);
9692               if(src->type == MRI_LONG)
9693                 val = MRILvox(src, i, j, k);
9694               if(src->type == MRI_FLOAT)
9695                 val = MRIFvox(src, i, j, k);
9696 
9697               val = dest_min + scale * (val - src_min);
9698 
9699               if(dest->type == MRI_UCHAR)
9700                 {
9701                   if(val < UCHAR_MIN)
9702                     val = UCHAR_MIN;
9703                   if(val > UCHAR_MAX)
9704                     val = UCHAR_MAX;
9705                   MRIvox(dest, i, j, k) = (unsigned char)val;
9706                 }
9707               if(dest->type == MRI_SHORT)
9708                 {
9709                   if(val < SHORT_MIN)
9710                     val = SHORT_MIN;
9711                   if(val > SHORT_MAX)
9712                     val = SHORT_MAX;
9713                   MRISvox(dest, i, j, k) = (short)val;
9714                 }
9715               if(dest->type == MRI_INT)
9716                 {
9717                   if(val < INT_MIN)
9718                     val = INT_MIN;
9719                   if(val > INT_MAX)
9720                     val = INT_MAX;
9721                   MRIIvox(dest, i, j, k) = (int)val;
9722                 }
9723               if(dest->type == MRI_LONG)
9724                 {
9725                   if(val < LONG_MIN)
9726                     val = LONG_MIN;
9727                   if(val > LONG_MAX)
9728                     val = LONG_MAX;
9729                   MRILvox(dest, i, j, k) = (long)val;
9730                 }
9731 
9732             }
9733 
9734     }
9735 
9736   return(dest);
9737 
9738 } /* end MRIchangeType() */
9739 
9740 /*-----------------------------------------------------*/
9741 MATRIX *MRIgetResampleMatrix(MRI *src, MRI *template_vol)
9742 {
9743 
9744   MATRIX *src_mat, *dest_mat; /* from i to ras */
9745   float src_det, dest_det;
9746   MATRIX *src_inv, *m;
9747 
9748   /* ----- fake the ras values if ras_good_flag is not set ----- */
9749   int src_slice_direction = getSliceDirection(src);
9750   if(!src->ras_good_flag
9751      && (src_slice_direction != MRI_CORONAL)
9752      && (src_slice_direction != MRI_SAGITTAL)
9753      && (src_slice_direction != MRI_HORIZONTAL))
9754     {
9755       ErrorReturn
9756         (NULL,
9757          (ERROR_BADPARM,
9758           "MRIresample(): source volume orientation is unknown"));
9759     }
9760 
9761   /*
9762 
9763   : solve each row of src_mat * [midx;midy;midz;1] = centerr, centera, centers
9764   and for dest
9765 
9766   S = M * s_v
9767 
9768   where M = [(x_r y_r z_r)(xsize  0     0  )  s14]
9769       s_v = (center_x)   S = (c_r)   etc.
9770   [(x_a y_a z_a)(  0  ysize   0  )  s24]        (center_y)       (c_a)
9771   [(x_s y_s z_s)(  0    0   zsize)  s34]        (center_z)       (c_s)
9772   [       0        0       0         1 ]        (    1   )       ( 1 )
9773 
9774   Write M = [  m    s],  s_v = (c_v), S = (c_R), then  c_R = m * c_v + s or
9775   [ 0 0 0 1]         ( 1 )      ( 1 )
9776 
9777   The translation s is given by   s = c_R - m*c_v
9778 
9779   Note the convention c_(r,a,s) being defined in
9780   terms of c_v = (width/2., height/2, depth/2.),
9781   not ((width-1)/2, (height-1)/2, (depth-1)/2).
9782 
9783   */
9784 
9785   src_mat = extract_i_to_r(src); // error when allocation fails
9786   if(src_mat == NULL)
9787     return NULL; // did ErrorPrintf in extract_i_to_r()
9788 
9789   dest_mat = extract_i_to_r(template_vol); // error when allocation fails
9790   if(dest_mat == NULL)
9791     {
9792       MatrixFree(&src_mat);
9793       return NULL; // did ErrorPrintf in extract_i_to_r()
9794     }
9795 
9796   // error check
9797   src_det = MatrixDeterminant(src_mat);
9798   dest_det = MatrixDeterminant(dest_mat);
9799 
9800   if(src_det == 0.0)
9801     {
9802       errno = 0;
9803       ErrorPrintf
9804         (ERROR_BADPARM,
9805          "MRIresample(): source matrix has zero determinant; matrix is:");
9806       MatrixPrint(stderr, src_mat);
9807       MatrixFree(&src_mat);
9808       MatrixFree(&dest_mat);
9809       return(NULL);
9810     }
9811 
9812   if(dest_det == 0.0)
9813     {
9814       errno = 0;
9815       ErrorPrintf
9816         (ERROR_BADPARM,
9817          "MRIresample(): destination matrix has zero determinant; matrix is:");
9818       MatrixPrint(stderr, dest_mat);
9819       MatrixFree(&src_mat);
9820       MatrixFree(&dest_mat);
9821       return(NULL);
9822     }
9823 
9824   src_inv = MatrixInverse(src_mat, NULL);
9825 
9826   if(src_inv == NULL)
9827     {
9828       errno = 0;
9829       ErrorPrintf
9830         (ERROR_BADPARM,
9831          "MRIresample(): error inverting matrix; determinant is "
9832          "%g, matrix is:", src_det);
9833       MatrixPrint(stderr, src_mat);
9834       MatrixFree(&src_mat);
9835       MatrixFree(&dest_mat);
9836       return(NULL);
9837     }
9838 
9839   m = MatrixMultiply(src_inv, dest_mat, NULL);
9840   if(m == NULL)
9841     return(NULL);
9842 
9843   MatrixFree(&src_inv);
9844   MatrixFree(&src_mat);
9845   MatrixFree(&dest_mat);
9846 
9847   if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
9848     {
9849       printf("MRIresample() matrix is:\n");
9850       MatrixPrint(stdout, m);
9851     }
9852   return(m) ;
9853 
9854 } /* end MRIreslice() */
9855 
9856 
9857 MRI *
9858 MRIresample(MRI *src, MRI *template_vol, int resample_type)
9859 {
9860   return(MRIresampleFill(src, template_vol, resample_type, 0)) ;
9861 } /* end MRIresample() */
9862 
9863 
9864 MRI *MRIresampleFill
9865 (MRI *src, MRI *template_vol, int resample_type, float fill_val)
9866 {
9867 
9868   MRI *dest = NULL;
9869   MATRIX *m;
9870   int di, dj, dk;
9871   int si, sj, sk;
9872   float si_f, sj_f, sk_f;
9873   float si_ff, sj_ff, sk_ff;
9874   MATRIX *sp, *dp;
9875   float val, val000, val001, val010, val011, val100, val101, val110, val111;
9876   float w000, w001, w010, w011, w100, w101, w110, w111;
9877   float si_f2, sj_f2, sk_f2;
9878   float ii2, ij2, ik2, isi_f2, isj_f2, isk_f2;
9879   float w[8];
9880   int wi[8];
9881   int mwi;
9882   Real pval;
9883   int i_good_flag, i1_good_flag;
9884   int j_good_flag, j1_good_flag;
9885   int k_good_flag, k1_good_flag;
9886 
9887   /* ----- keep the compiler quiet ----- */
9888   val = 0.0;
9889   val000 = val001 = val010 = val011 = val100 = val101 = val110 = val111 = 0.0;
9890 
9891 #if 0
9892   if(src->type != template_vol->type)
9893     {
9894       ErrorReturn
9895         (NULL,
9896          (ERROR_UNSUPPORTED,
9897           "MRIresample(): source and destination types must be identical"));
9898     }
9899 #endif
9900 
9901   /* ----- fake the ras values if ras_good_flag is not set ----- */
9902   if(!src->ras_good_flag)
9903     printf
9904       ("MRIresample(): WARNING: ras_good_flag "
9905        "is not set, changing orientation\n"
9906        "to default.\n");
9907 
9908   // get dst voxel -> src voxel transform
9909   m = MRIgetResampleMatrix(src, template_vol);
9910   if(m == NULL)
9911     return(NULL);
9912 
9913   if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
9914     {
9915       printf("MRIresample() matrix is:\n");
9916       MatrixPrint(stdout, m);
9917     }
9918 
9919   dest = MRIalloc(template_vol->width,
9920                   template_vol->height,
9921                   template_vol->depth,
9922                   src->type);
9923   if(dest == NULL)
9924     return(NULL);
9925   MRIreplaceValues(dest, dest, 0.0f, fill_val) ;
9926 
9927   MRIcopyHeader(template_vol, dest);
9928   MRIcopyPulseParameters(src, dest) ;
9929 
9930   sp = MatrixAlloc(4, 1, MATRIX_REAL);
9931   dp = MatrixAlloc(4, 1, MATRIX_REAL);
9932 
9933   *MATRIX_RELT(dp, 4, 1) = 1.0;
9934 
9935   for(di = 0;di < template_vol->width;di++)
9936     {
9937       for(dj = 0;dj < template_vol->height;dj++)
9938         {
9939           for(dk = 0;dk < template_vol->depth;dk++)
9940             {
9941 
9942               *MATRIX_RELT(dp, 1, 1) = (float)di;
9943               *MATRIX_RELT(dp, 2, 1) = (float)dj;
9944               *MATRIX_RELT(dp, 3, 1) = (float)dk;
9945 
9946               MatrixMultiply(m, dp, sp);
9947 
9948               si_ff = *MATRIX_RELT(sp, 1, 1);
9949               sj_ff = *MATRIX_RELT(sp, 2, 1);
9950               sk_ff = *MATRIX_RELT(sp, 3, 1);
9951 
9952               si = (int)floor(si_ff);
9953               sj = (int)floor(sj_ff);
9954               sk = (int)floor(sk_ff);
9955 
9956               if (si == 147 && sj == 91 && sk == 86)
9957                 DiagBreak() ;
9958               if (di == 129 && dj == 164 && dk == 147)
9959                 DiagBreak() ;
9960               si_f = si_ff - si;
9961               sj_f = sj_ff - sj;
9962               sk_f = sk_ff - sk;
9963 
9964 #if 0
9965               if(di % 20 == 0 && dj == di && dk == dj)
9966                 {
9967                   printf("MRIresample() sample point: %3d %3d %3d: "
9968                          "%f (%3d + %f) %f (%3d + %f) %f (%3d + %f)\n",
9969                          di, dj, dk,
9970                          si_ff, si, si_f,
9971                          sj_ff, sj, sj_f,
9972                          sk_ff, sk, sk_f);
9973                 }
9974 #endif
9975 
9976               if(resample_type == SAMPLE_SINC)
9977                 {
9978                   MRIsincSampleVolume(src, si_ff, sj_ff, sk_ff, 5, &pval);
9979                   val = (float)pval;
9980                 }
9981               else if(resample_type == SAMPLE_CUBIC)
9982                 {
9983                   MRIcubicSampleVolume(src, si_ff, sj_ff, sk_ff, &pval);
9984                   val = (float)pval;
9985                 }
9986               else
9987                 {
9988                   i_good_flag = (si >= 0 && si < src->width);
9989                   i1_good_flag = (si+1 >= 0 && si+1 < src->width);
9990                   j_good_flag = (sj >= 0 && sj < src->height);
9991                   j1_good_flag = (sj+1 >= 0 && sj+1 < src->height);
9992                   k_good_flag = (sk >= 0 && sk < src->depth);
9993                   k1_good_flag = (sk+1 >= 0 && sk+1 < src->depth);
9994 
9995                   if(src->type == MRI_UCHAR)
9996                     {
9997                       val000 = ( !i_good_flag ||
9998                                  !j_good_flag ||
9999                                  !k_good_flag ? 0.0 :
10000                                  (float)MRIvox(src, si    , sj    , sk    ));
10001                       val001 = ( !i_good_flag ||
10002                                  !j_good_flag ||
10003                                  !k1_good_flag ? 0.0 :
10004                                  (float)MRIvox(src, si    , sj    , sk + 1));
10005                       val010 = ( !i_good_flag ||
10006                                  !j1_good_flag ||
10007                                  !k_good_flag ? 0.0 :
10008                                  (float)MRIvox(src, si    , sj + 1, sk    ));
10009                       val011 = ( !i_good_flag ||
10010                                  !j1_good_flag ||
10011                                  !k1_good_flag ? 0.0 :
10012                                  (float)MRIvox(src, si    , sj + 1, sk + 1));
10013                       val100 = (!i1_good_flag ||
10014                                 !j_good_flag ||
10015                                 !k_good_flag ? 0.0 :
10016                                 (float)MRIvox(src, si + 1, sj    , sk    ));
10017                       val101 = (!i1_good_flag ||
10018                                 !j_good_flag ||
10019                                 !k1_good_flag ? 0.0 :
10020                                 (float)MRIvox(src, si + 1, sj    , sk + 1));
10021                       val110 = (!i1_good_flag ||
10022                                 !j1_good_flag ||
10023                                 !k_good_flag ? 0.0 :
10024                                 (float)MRIvox(src, si + 1, sj + 1, sk    ));
10025                       val111 = (!i1_good_flag ||
10026                                 !j1_good_flag ||
10027                                 !k1_good_flag ? 0.0 :
10028                                 (float)MRIvox(src, si + 1, sj + 1, sk + 1));
10029                     }
10030 
10031                   if (si == 154 && sj == 134 && sk == 136)
10032                     DiagBreak() ;
10033 
10034                   if(src->type == MRI_SHORT)
10035                     {
10036                       val000 = ( !i_good_flag ||
10037                                  !j_good_flag ||
10038                                  !k_good_flag ? 0.0 :
10039                                  (float)MRISvox(src, si    , sj    , sk    ));
10040                       val001 = ( !i_good_flag ||
10041                                  !j_good_flag ||
10042                                  !k1_good_flag ? 0.0 :
10043                                  (float)MRISvox(src, si    , sj    , sk + 1));
10044                       val010 = ( !i_good_flag ||
10045                                  !j1_good_flag ||
10046                                  !k_good_flag ? 0.0 :
10047                                  (float)MRISvox(src, si    , sj + 1, sk    ));
10048                       val011 = ( !i_good_flag ||
10049                                  !j1_good_flag ||
10050                                  !k1_good_flag ? 0.0 :
10051                                  (float)MRISvox(src, si    , sj + 1, sk + 1));
10052                       val100 = (!i1_good_flag ||
10053                                 !j_good_flag ||
10054                                 !k_good_flag ? 0.0 :
10055                                 (float)MRISvox(src, si + 1, sj    , sk    ));
10056                       val101 = (!i1_good_flag ||
10057                                 !j_good_flag ||
10058                                 !k1_good_flag ? 0.0 :
10059                                 (float)MRISvox(src, si + 1, sj    , sk + 1));
10060                       val110 = (!i1_good_flag ||
10061                                 !j1_good_flag ||
10062                                 !k_good_flag ? 0.0 :
10063                                 (float)MRISvox(src, si + 1, sj + 1, sk    ));
10064                       val111 = (!i1_good_flag ||
10065                                 !j1_good_flag ||
10066                                 !k1_good_flag ? 0.0 :
10067                                 (float)MRISvox(src, si + 1, sj + 1, sk + 1));
10068                     }
10069 
10070                   if(src->type == MRI_INT)
10071                     {
10072                       val000 = ( !i_good_flag ||
10073                                  !j_good_flag ||
10074                                  !k_good_flag ? 0.0 :
10075                                  (float)MRIIvox(src, si    , sj    , sk    ));
10076                       val001 = ( !i_good_flag ||
10077                                  !j_good_flag ||
10078                                  !k1_good_flag ? 0.0 :
10079                                  (float)MRIIvox(src, si    , sj    , sk + 1));
10080                       val010 = ( !i_good_flag ||
10081                                  !j1_good_flag ||
10082                                  !k_good_flag ? 0.0 :
10083                                  (float)MRIIvox(src, si    , sj + 1, sk    ));
10084                       val011 = ( !i_good_flag ||
10085                                  !j1_good_flag ||
10086                                  !k1_good_flag ? 0.0 :
10087                                  (float)MRIIvox(src, si    , sj + 1, sk + 1));
10088                       val100 = (!i1_good_flag ||
10089                                 !j_good_flag ||
10090                                 !k_good_flag ? 0.0 :
10091                                 (float)MRIIvox(src, si + 1, sj    , sk    ));
10092                       val101 = (!i1_good_flag ||
10093                                 !j_good_flag ||
10094                                 !k1_good_flag ? 0.0 :
10095                                 (float)MRIIvox(src, si + 1, sj    , sk + 1));
10096                       val110 = (!i1_good_flag ||
10097                                 !j1_good_flag ||
10098                                 !k_good_flag ? 0.0 :
10099                                 (float)MRIIvox(src, si + 1, sj + 1, sk    ));
10100                       val111 = (!i1_good_flag ||
10101                                 !j1_good_flag ||
10102                                 !k1_good_flag ? 0.0 :
10103                                 (float)MRIIvox(src, si + 1, sj + 1, sk + 1));
10104                     }
10105 
10106                   if(src->type == MRI_LONG)
10107                     {
10108                       val000 = ( !i_good_flag ||
10109                                  !j_good_flag ||
10110                                  !k_good_flag ? 0.0 :
10111                                  (float)MRILvox(src, si    , sj    , sk    ));
10112                       val001 = ( !i_good_flag ||
10113                                  !j_good_flag ||
10114                                  !k1_good_flag ? 0.0 :
10115                                  (float)MRILvox(src, si    , sj    , sk + 1));
10116                       val010 = ( !i_good_flag ||
10117                                  !j1_good_flag ||
10118                                  !k_good_flag ? 0.0 :
10119                                  (float)MRILvox(src, si    , sj + 1, sk    ));
10120                       val011 = ( !i_good_flag ||
10121                                  !j1_good_flag ||
10122                                  !k1_good_flag ? 0.0 :
10123                                  (float)MRILvox(src, si    , sj + 1, sk + 1));
10124                       val100 = (!i1_good_flag ||
10125                                 !j_good_flag ||
10126                                 !k_good_flag ? 0.0 :
10127                                 (float)MRILvox(src, si + 1, sj    , sk    ));
10128                       val101 = (!i1_good_flag ||
10129                                 !j_good_flag ||
10130                                 !k1_good_flag ? 0.0 :
10131                                 (float)MRILvox(src, si + 1, sj    , sk + 1));
10132                       val110 = (!i1_good_flag ||
10133                                 !j1_good_flag ||
10134                                 !k_good_flag ? 0.0 :
10135                                 (float)MRILvox(src, si + 1, sj + 1, sk    ));
10136                       val111 = (!i1_good_flag ||
10137                                 !j1_good_flag ||
10138                                 !k1_good_flag ? 0.0 :
10139                                 (float)MRILvox(src, si + 1, sj + 1, sk + 1));
10140                     }
10141 
10142                   if(src->type == MRI_FLOAT)
10143                     {
10144                       val000 = ( !i_good_flag ||
10145                                  !j_good_flag ||
10146                                  !k_good_flag ? 0.0 :
10147                                  (float)MRIFvox(src, si    , sj    , sk    ));
10148                       val001 = ( !i_good_flag ||
10149                                  !j_good_flag ||
10150                                  !k1_good_flag ? 0.0 :
10151                                  (float)MRIFvox(src, si    , sj    , sk + 1));
10152                       val010 = ( !i_good_flag ||
10153                                  !j1_good_flag ||
10154                                  !k_good_flag ? 0.0 :
10155                                  (float)MRIFvox(src, si    , sj + 1, sk    ));
10156                       val011 = ( !i_good_flag ||
10157                                  !j1_good_flag ||
10158                                  !k1_good_flag ? 0.0 :
10159                                  (float)MRIFvox(src, si    , sj + 1, sk + 1));
10160                       val100 = (!i1_good_flag ||
10161                                 !j_good_flag ||
10162                                 !k_good_flag ? 0.0 :
10163                                 (float)MRIFvox(src, si + 1, sj    , sk    ));
10164                       val101 = (!i1_good_flag ||
10165                                 !j_good_flag ||
10166                                 !k1_good_flag ? 0.0 :
10167                                 (float)MRIFvox(src, si + 1, sj    , sk + 1));
10168                       val110 = (!i1_good_flag ||
10169                                 !j1_good_flag ||
10170                                 !k_good_flag ? 0.0 :
10171                                 (float)MRIFvox(src, si + 1, sj + 1, sk    ));
10172                       val111 = (!i1_good_flag ||
10173                                 !j1_good_flag ||
10174                                 !k1_good_flag ? 0.0 :
10175                                 (float)MRIFvox(src, si + 1, sj + 1, sk + 1));
10176                     }
10177 
10178                   if(resample_type == SAMPLE_TRILINEAR)
10179                     {
10180                       val = (1.0-si_f) * (1.0-sj_f) * (1.0-sk_f) * val000 +
10181                         (1.0-si_f) * (1.0-sj_f) * (    sk_f) * val001 +
10182                         (1.0-si_f) * (    sj_f) * (1.0-sk_f) * val010 +
10183                         (1.0-si_f) * (    sj_f) * (    sk_f) * val011 +
10184                         (    si_f) * (1.0-sj_f) * (1.0-sk_f) * val100 +
10185                         (    si_f) * (1.0-sj_f) * (    sk_f) * val101 +
10186                         (    si_f) * (    sj_f) * (1.0-sk_f) * val110 +
10187                         (    si_f) * (    sj_f) * (    sk_f) * val111;
10188                     }
10189 
10190                   if(resample_type == SAMPLE_NEAREST)
10191                     {
10192                       if(si_f < 0.5)
10193                         {
10194                           if(sj_f < 0.5)
10195                             {
10196                               if(sk_f < 0.5)
10197                                 val = val000;
10198                               else
10199                                 val = val001;
10200                             }
10201                           else
10202                             {
10203                               if(sk_f < 0.5)
10204                                 val = val010;
10205                               else
10206                                 val = val011;
10207                             }
10208                         }
10209                       else
10210                         {
10211                           if(sj_f < 0.5)
10212                             {
10213                               if(sk_f < 0.5)
10214                                 val = val100;
10215                               else
10216                                 val = val101;
10217                             }
10218                           else
10219                             {
10220                               if(sk_f < 0.5)
10221                                 val = val110;
10222                               else
10223                                 val = val111;
10224                             }
10225                         }
10226                     }
10227 
10228                   if(resample_type == SAMPLE_WEIGHTED)
10229                     {
10230                       /* unfinished */
10231                       si_f2 = si_f * si_f;
10232                       sj_f2 = sj_f * sj_f;
10233                       sk_f2 = sk_f * sk_f;
10234 
10235                       ii2 = 1. / (1 - 2*si_f + si_f2);
10236                       ij2 = 1. / (1 - 2*sj_f + sj_f2);
10237                       ik2 = 1. / (1 - 2*sk_f + sk_f2);
10238 
10239                       isi_f2 = 1 / si_f2;
10240                       isj_f2 = 1 / sj_f2;
10241                       isk_f2 = 1 / sk_f2;
10242 
10243                       w000 =   ii2    + ij2    + ik2;
10244                       w001 =   ii2    + ij2    + isk_f2;
10245                       w010 =   ii2    + isj_f2 + ik2;
10246                       w011 =   ii2    + isj_f2 + isk_f2;
10247                       w100 =   isi_f2 + ij2    + ik2;
10248                       w101 =   isi_f2 + ij2    + isk_f2;
10249                       w110 =   isi_f2 + isj_f2 + ik2;
10250                       w111 =   isi_f2 + isj_f2 + isk_f2;
10251 
10252                       w[0] = w[1] = w[2] = w[3] =
10253                         w[4] = w[5] = w[6] = w[7] = 0.0;
10254 
10255                       wi[0] = 0;
10256                       wi[1] = 1;
10257                       wi[2] = 2;
10258                       wi[3] = 3;
10259                       wi[4] = 4;
10260                       wi[5] = 5;
10261                       wi[6] = 6;
10262                       wi[7] = 7;
10263 
10264                       if(val001 == val000)
10265                         wi[1] = 0;
10266 
10267                       if(val010 == val001)
10268                         wi[2] = 1;
10269                       if(val010 == val000)
10270                         wi[2] = 0;
10271 
10272                       if(val011 == val010)
10273                         wi[3] = 2;
10274                       if(val011 == val001)
10275                         wi[3] = 1;
10276                       if(val011 == val000)
10277                         wi[3] = 0;
10278 
10279                       if(val100 == val011)
10280                         wi[4] = 3;
10281                       if(val100 == val010)
10282                         wi[4] = 2;
10283                       if(val100 == val001)
10284                         wi[4] = 1;
10285                       if(val100 == val000)
10286                         wi[4] = 0;
10287 
10288                       if(val101 == val100)
10289                         wi[5] = 4;
10290                       if(val101 == val011)
10291                         wi[5] = 3;
10292                       if(val101 == val010)
10293                         wi[5] = 2;
10294                       if(val101 == val001)
10295                         wi[5] = 1;
10296                       if(val101 == val000)
10297                         wi[5] = 0;
10298 
10299                       if(val110 == val101)
10300                         wi[6] = 5;
10301                       if(val110 == val100)
10302                         wi[6] = 4;
10303                       if(val110 == val011)
10304                         wi[6] = 3;
10305                       if(val110 == val010)
10306                         wi[6] = 2;
10307                       if(val110 == val001)
10308                         wi[6] = 1;
10309                       if(val110 == val000)
10310                         wi[6] = 0;
10311 
10312                       if(val111 == val110)
10313                         wi[7] = 6;
10314                       if(val111 == val101)
10315                         wi[7] = 5;
10316                       if(val111 == val100)
10317                         wi[7] = 4;
10318                       if(val111 == val011)
10319                         wi[7] = 3;
10320                       if(val111 == val010)
10321                         wi[7] = 2;
10322                       if(val111 == val001)
10323                         wi[7] = 1;
10324                       if(val111 == val000)
10325                         wi[7] = 0;
10326 
10327                       w[wi[0]] += w000;
10328                       w[wi[1]] += w001;
10329                       w[wi[2]] += w010;
10330                       w[wi[3]] += w011;
10331                       w[wi[4]] += w100;
10332                       w[wi[5]] += w101;
10333                       w[wi[6]] += w110;
10334                       w[wi[7]] += w111;
10335 
10336                       mwi = 0;
10337 
10338                       if(w[1] > w[mwi])
10339                         mwi = 1;
10340                       if(w[2] > w[mwi])
10341                         mwi = 2;
10342                       if(w[3] > w[mwi])
10343                         mwi = 3;
10344                       if(w[4] > w[mwi])
10345                         mwi = 4;
10346                       if(w[5] > w[mwi])
10347                         mwi = 5;
10348                       if(w[6] > w[mwi])
10349                         mwi = 6;
10350                       if(w[7] > w[mwi])
10351                         mwi = 7;
10352 
10353                       if(mwi == 0)
10354                         val = val000;
10355                       if(mwi == 1)
10356                         val = val001;
10357                       if(mwi == 2)
10358                         val = val010;
10359                       if(mwi == 3)
10360                         val = val011;
10361                       if(mwi == 4)
10362                         val = val100;
10363                       if(mwi == 5)
10364                         val = val101;
10365                       if(mwi == 6)
10366                         val = val110;
10367                       if(mwi == 7)
10368                         val = val111;
10369 
10370                     }
10371 
10372                 }
10373 
10374               if(dest->type == MRI_UCHAR)
10375                 MRIvox(dest, di, dj, dk) = (unsigned char)val;
10376               if(dest->type == MRI_SHORT)
10377                 MRISvox(dest, di, dj, dk) = (short)val;
10378               if(dest->type == MRI_INT)
10379                 MRIIvox(dest, di, dj, dk) = (int)val;
10380               if(dest->type == MRI_LONG)
10381                 MRILvox(dest, di, dj, dk) = (long)val;
10382               if(dest->type == MRI_FLOAT)
10383                 MRIFvox(dest, di, dj, dk) = (float)val;
10384 
10385             }
10386         }
10387     }
10388 
10389   {
10390     MATRIX  *m_old_voxel_to_ras, *m_voxel_to_ras,
10391       *m_old_ras_to_voxel, *v_ras, *v_vox, *m_new_ras_to_voxel, *v_vox2 ;
10392 
10393     m_old_voxel_to_ras = MRIgetVoxelToRasXform(src) ;
10394 
10395     m_voxel_to_ras = MatrixMultiply(m_old_voxel_to_ras, m, NULL) ;
10396 
10397     dest->x_r = *MATRIX_RELT(m_voxel_to_ras,1,1)/dest->xsize;
10398     dest->x_a = *MATRIX_RELT(m_voxel_to_ras,2,1)/dest->xsize;
10399     dest->x_s = *MATRIX_RELT(m_voxel_to_ras,3,1)/dest->xsize;
10400 
10401     dest->y_r = *MATRIX_RELT(m_voxel_to_ras,1,2)/dest->ysize;
10402     dest->y_a = *MATRIX_RELT(m_voxel_to_ras,2,2)/dest->ysize;
10403     dest->y_s = *MATRIX_RELT(m_voxel_to_ras,3,2)/dest->ysize;
10404 
10405     dest->z_r = *MATRIX_RELT(m_voxel_to_ras,1,3)/dest->zsize;
10406     dest->z_a = *MATRIX_RELT(m_voxel_to_ras,2,3)/dest->zsize;
10407     dest->z_s = *MATRIX_RELT(m_voxel_to_ras,3,3)/dest->zsize;
10408 
10409     /* compute the RAS coordinates of the center of the dest. image
10410        and put them in c_r, c_a, and c_s.
10411 
10412        C = M * c_v
10413     */
10414     v_vox = VectorAlloc(4, MATRIX_REAL) ;
10415 
10416     /* voxel coords of center of dest image */
10417     VECTOR_ELT(v_vox,4) = 1.0 ;
10418     VECTOR_ELT(v_vox,1) = (dest->width)/2.0 ;
10419     VECTOR_ELT(v_vox,2) = (dest->height)/2.0 ;
10420     VECTOR_ELT(v_vox,3) = (dest->depth)/2.0 ;
10421 
10422     v_vox2 =
10423       MatrixMultiply(m, v_vox, NULL) ; /* voxel coords in source image */
10424     v_ras =
10425       MatrixMultiply(m_old_voxel_to_ras, v_vox2, NULL) ; /* ras cntr of dest */
10426 
10427     dest->c_r = VECTOR_ELT(v_ras, 1);
10428     dest->c_a = VECTOR_ELT(v_ras, 2);
10429     dest->c_s = VECTOR_ELT(v_ras, 3);
10430     dest->ras_good_flag = 1 ;
10431 
10432     if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
10433       {
10434         m_new_ras_to_voxel = MRIgetRasToVoxelXform(dest) ;
10435         m_old_ras_to_voxel = MRIgetRasToVoxelXform(src) ;
10436         V3_X(v_ras) = V3_Y(v_ras) = V3_Z(v_ras) = 0.0 ;
10437         MatrixMultiply(m_old_ras_to_voxel, v_ras, v_vox) ;
10438         printf("old RAS (0,0,0) -> (%2.0f, %2.0f, %2.0f)\n",
10439                VECTOR_ELT(v_vox,1), VECTOR_ELT(v_vox,2), VECTOR_ELT(v_vox,3)) ;
10440         MatrixMultiply(m_new_ras_to_voxel, v_ras, v_vox) ;
10441         printf("new RAS (0,0,0) -> (%2.0f, %2.0f, %2.0f)\n",
10442                VECTOR_ELT(v_vox,1), VECTOR_ELT(v_vox,2), VECTOR_ELT(v_vox,3)) ;
10443         MatrixFree(&m_new_ras_to_voxel) ; MatrixFree(&m_old_ras_to_voxel) ;
10444       }
10445 
10446     MatrixFree(&v_vox) ; MatrixFree(&v_vox2) ; MatrixFree(&v_ras) ;
10447     MatrixFree(&m_voxel_to_ras) ; MatrixFree(&m_old_voxel_to_ras) ;
10448   }
10449 
10450 
10451   MatrixFree(&dp);
10452   MatrixFree(&sp);
10453   MatrixFree(&m);
10454 
10455   return(dest);
10456 
10457 } /* end MRIresample() */
10458 
10459 int MRIlimits(MRI *mri, float *min, float *max)
10460 {
10461 
10462   float val;
10463   int i, j, k;
10464 
10465   if(mri == NULL)
10466     return(NO_ERROR);
10467 
10468   if(mri->slices == NULL)
10469     return(NO_ERROR);
10470 
10471   if(mri->type == MRI_UCHAR)
10472     {
10473       *min = *max = (float)MRIvox(mri, 0, 0, 0);
10474       for(i = 0;i < mri->width;i++)
10475         for(j = 0;j < mri->height;j++)
10476           for(k = 0;k < mri->depth;k++)
10477             {
10478               val = (float)MRIvox(mri, i, j, k);
10479               if(val < *min)
10480                 *min = val;
10481               if(val > *max)
10482                 *max = val;
10483             }
10484 
10485     }
10486 
10487   if(mri->type == MRI_SHORT)
10488     {
10489 
10490       *min = *max = (float)MRISvox(mri, 0, 0, 0);
10491 
10492       for(i = 0;i < mri->width;i++)
10493         for(j = 0;j < mri->height;j++)
10494           for(k = 0;k < mri->depth;k++)
10495             {
10496               val = (float)MRISvox(mri, i, j, k);
10497               if(val < *min)
10498                 *min = val;
10499               if(val > *max)
10500                 *max = val;
10501             }
10502 
10503     }
10504 
10505   if(mri->type == MRI_INT)
10506     {
10507 
10508       *min = *max = (float)MRILvox(mri, 0, 0, 0);
10509 
10510       for(i = 0;i < mri->width;i++)
10511         for(j = 0;j < mri->height;j++)
10512           for(k = 0;k < mri->depth;k++)
10513             {
10514               val = (float)MRILvox(mri, i, j, k);
10515               if(val < *min)
10516                 *min = val;
10517               if(val > *max)
10518                 *max = val;
10519             }
10520 
10521     }
10522 
10523   if(mri->type == MRI_LONG)
10524     {
10525 
10526       *min = *max = (float)MRILvox(mri, 0, 0, 0);
10527 
10528       for(i = 0;i < mri->width;i++)
10529         for(j = 0;j < mri->height;j++)
10530           for(k = 0;k < mri->depth;k++)
10531             {
10532               val = (float)MRILvox(mri, i, j, k);
10533               if(val < *min)
10534                 *min = val;
10535               if(val > *max)
10536                 *max = val;
10537             }
10538 
10539     }
10540 
10541   if(mri->type == MRI_FLOAT)
10542     {
10543 
10544       *min = *max = (float)MRIFvox(mri, 0, 0, 0);
10545 
10546       for(i = 0;i < mri->width;i++)
10547         for(j = 0;j < mri->height;j++)
10548           for(k = 0;k < mri->depth;k++)
10549             {
10550               val = (float)MRIFvox(mri, i, j, k);
10551               if(val < *min)
10552                 *min = val;
10553               if(val > *max)
10554                 *max = val;
10555             }
10556 
10557     }
10558 
10559   return(NO_ERROR);
10560 
10561 } /* end MRIlimits() */
10562 
10563 int MRIprintStats(MRI *mri, FILE *stream)
10564 {
10565 
10566   float min, max, mean, std;
10567   int n;
10568   double com[3];
10569 
10570   MRIstats(mri, &min, &max, &n, &mean, &std);
10571 
10572   fprintf(stream, "%d values\n", n);
10573   fprintf(stream, "min = %g\n", min);
10574   fprintf(stream, "max = %g\n", max);
10575   fprintf(stream, "mean = %g\n", mean);
10576   fprintf(stream, "std = %g\n", std);
10577 
10578   MRIcenterOfMass(mri, com, 0);
10579 
10580   fprintf(stream, "com = %g %g %g\n", com[0], com[1], com[2]);
10581 
10582   return(NO_ERROR);
10583 
10584 } /* end MRIprintStats() */
10585 
10586 int MRIstats
10587 (MRI *mri, float *min, float *max, int *n_voxels, float *mean, float *std)
10588 {
10589 
10590   float val;
10591   float sum, sq_sum;
10592   int i, j, k, t;
10593   float n;
10594 
10595   if(mri == NULL)
10596     return(NO_ERROR);
10597 
10598   if(mri->slices == NULL)
10599     return(NO_ERROR);
10600 
10601   sum = sq_sum = 0.0;
10602   *n_voxels = mri->width * mri->height * mri->depth * mri->nframes;
10603   n = (float)(*n_voxels);
10604 
10605   if(mri->type == MRI_UCHAR)
10606     {
10607 
10608       *max = *min = MRIseq_vox(mri, 0, 0, 0, 0);
10609 
10610       for(i = 0;i < mri->width;i++)
10611         for(j = 0;j < mri->height;j++)
10612           for(k = 0;k < mri->depth;k++)
10613             for(t = 0;t < mri->nframes;t++)
10614               {
10615 
10616                 val = (float)MRIseq_vox(mri, i, j, k, t);
10617 
10618                 if(val < *min)
10619                   *min = val;
10620                 if(val > *max)
10621                   *max = val;
10622 
10623                 sum += val;
10624                 sq_sum += val * val;
10625 
10626               }
10627 
10628     }
10629 
10630   if(mri->type == MRI_SHORT)
10631     {
10632 
10633       *min = *max = (float)MRISseq_vox(mri, 0, 0, 0, 0);
10634 
10635       for(i = 0;i < mri->width;i++)
10636         for(j = 0;j < mri->height;j++)
10637           for(k = 0;k < mri->depth;k++)
10638             for(t = 0;t < mri->nframes;t++)
10639               {
10640 
10641                 val = (float)MRISseq_vox(mri, i, j, k, t);
10642 
10643                 if(val < *min)
10644                   *min = val;
10645                 if(val > *max)
10646                   *max = val;
10647 
10648                 sum += val;
10649                 sq_sum += val * val;
10650 
10651               }
10652 
10653     }
10654 
10655   if(mri->type == MRI_INT)
10656     {
10657 
10658       *min = *max = (float)MRILseq_vox(mri, 0, 0, 0, 0);
10659 
10660       for(i = 0;i < mri->width;i++)
10661         for(j = 0;j < mri->height;j++)
10662           for(k = 0;k < mri->depth;k++)
10663             for(t = 0;t < mri->nframes;t++)
10664               {
10665 
10666                 val = (float)MRILseq_vox(mri, i, j, k, t);
10667 
10668                 if(val < *min)
10669                   *min = val;
10670                 if(val > *max)
10671                   *max = val;
10672 
10673                 sum += val;
10674                 sq_sum += val * val;
10675 
10676               }
10677 
10678     }
10679 
10680   if(mri->type == MRI_LONG)
10681     {
10682 
10683       *min = *max = (float)MRILseq_vox(mri, 0, 0, 0, 0);
10684 
10685       for(i = 0;i < mri->width;i++)
10686         for(j = 0;j < mri->height;j++)
10687           for(k = 0;k < mri->depth;k++)
10688             for(t = 0;t < mri->nframes;t++)
10689               {
10690 
10691                 val = (float)MRILseq_vox(mri, i, j, k, t);
10692 
10693                 if(val < *min)
10694                   *min = val;
10695                 if(val > *max)
10696                   *max = val;
10697 
10698                 sum += val;
10699                 sq_sum += val * val;
10700 
10701               }
10702 
10703     }
10704 
10705   if(mri->type == MRI_FLOAT)
10706     {
10707 
10708       *min = *max = (float)MRIFseq_vox(mri, 0, 0, 0, 0);
10709 
10710       for(i = 0;i < mri->width;i++)
10711         for(j = 0;j < mri->height;j++)
10712           for(k = 0;k < mri->depth;k++)
10713             for(t = 0;t < mri->nframes;t++)
10714               {
10715 
10716                 val = (float)MRIFseq_vox(mri, i, j, k, t);
10717 
10718                 if(val < *min)
10719                   *min = val;
10720                 if(val > *max)
10721                   *max = val;
10722 
10723                 sum += val;
10724                 sq_sum += val * val;
10725 
10726               }
10727 
10728     }
10729 
10730   *mean = sum / n;
10731   *std = (sq_sum - n * (*mean) * (*mean)) / (n - 1.0);
10732 
10733   *std = sqrt(*std);
10734 
10735   return(NO_ERROR);
10736 
10737 } /* end MRIstats() */
10738 
10739 float MRIvolumeDeterminant(MRI *mri)
10740 {
10741 
10742   MATRIX *m;
10743   float det;
10744 
10745   m = MatrixAlloc(4, 4, MATRIX_REAL);
10746   if(m == NULL)
10747     return(0.0);
10748 
10749   stuff_four_by_four(m, mri->x_r, mri->y_r, mri->z_r, 0.0,
10750                      mri->x_a, mri->y_a, mri->z_a, 0.0,
10751                      mri->x_s, mri->y_s, mri->z_s, 0.0,
10752                      0.0,      0.0,      0.0, 1.0);
10753 
10754   det = MatrixDeterminant(m);
10755 
10756   MatrixFree(&m);
10757 
10758   return(det);
10759 
10760 } /* end MRIvolumeDeterminant() */
10761 
10762 int stuff_four_by_four(MATRIX *m, float m11, float m12, float m13, float m14,
10763                        float m21, float m22, float m23, float m24,
10764                        float m31, float m32, float m33, float m34,
10765                        float m41, float m42, float m43, float m44)
10766 {
10767 
10768   if(m == NULL)
10769     {
10770       ErrorReturn
10771         (ERROR_BADPARM,
10772          (ERROR_BADPARM,
10773           "stuff_four_by_four(): matrix is NULL"));
10774     }
10775 
10776   if(m->rows != 4 || m->cols != 4)
10777     {
10778       ErrorReturn
10779         (ERROR_BADPARM,
10780          (ERROR_BADPARM,
10781           "stuff_four_by_four(): matrix is not four-by-four"));
10782     }
10783 
10784   *MATRIX_RELT(m, 1, 1) = m11;
10785   *MATRIX_RELT(m, 1, 2) = m12;
10786   *MATRIX_RELT(m, 1, 3) = m13;
10787   *MATRIX_RELT(m, 1, 4) = m14;
10788   *MATRIX_RELT(m, 2, 1) = m21;
10789   *MATRIX_RELT(m, 2, 2) = m22;
10790   *MATRIX_RELT(m, 2, 3) = m23;
10791   *MATRIX_RELT(m, 2, 4) = m24;
10792   *MATRIX_RELT(m, 3, 1) = m31;
10793   *MATRIX_RELT(m, 3, 2) = m32;
10794   *MATRIX_RELT(m, 3, 3) = m33;
10795   *MATRIX_RELT(m, 3, 4) = m34;
10796   *MATRIX_RELT(m, 4, 1) = m41;
10797   *MATRIX_RELT(m, 4, 2) = m42;
10798   *MATRIX_RELT(m, 4, 3) = m43;
10799   *MATRIX_RELT(m, 4, 4) = m44;
10800 
10801   return(NO_ERROR);
10802 
10803 } /* end stuff_four_by_four() */
10804 
10805 int apply_i_to_r(MRI *mri, MATRIX *m)
10806 {
10807 
10808   float x_r, x_a, x_s;
10809   float y_r, y_a, y_s;
10810   float z_r, z_a, z_s;
10811   float mag;
10812   MATRIX *origin, *c;
10813 
10814   x_r = *MATRIX_RELT(m, 1, 1);
10815   x_a = *MATRIX_RELT(m, 2, 1);
10816   x_s = *MATRIX_RELT(m, 3, 1);
10817   mag = sqrt(x_r*x_r + x_a*x_a + x_s*x_s);
10818   mri->x_r = x_r / mag;  mri->x_a = x_a / mag;  mri->x_s = x_s / mag;
10819   mri->xsize = mag;
10820 
10821   y_r = *MATRIX_RELT(m, 1, 2);
10822   y_a = *MATRIX_RELT(m, 2, 2);
10823   y_s = *MATRIX_RELT(m, 3, 2);
10824   mag = sqrt(y_r*y_r + y_a*y_a + y_s*y_s);
10825   mri->y_r = y_r / mag;  mri->y_a = y_a / mag;  mri->y_s = y_s / mag;
10826   mri->ysize = mag;
10827 
10828   z_r = *MATRIX_RELT(m, 1, 3);
10829   z_a = *MATRIX_RELT(m, 2, 3);
10830   z_s = *MATRIX_RELT(m, 3, 3);
10831   mag = sqrt(z_r*z_r + z_a*z_a + z_s*z_s);
10832   mri->z_r = z_r / mag;  mri->z_a = z_a / mag;  mri->z_s = z_s / mag;
10833   mri->zsize = mag;
10834 
10835   origin = MatrixAlloc(4, 1, MATRIX_REAL);
10836   if(origin == NULL)
10837     {
10838       ErrorReturn
10839         (ERROR_BADPARM,
10840          (ERROR_BADPARM,
10841           "apply_i_to_r(): error allocating matrix"));
10842     }
10843   *MATRIX_RELT(origin, 1, 1) = (mri->width  - 1.0) / 2.0;
10844   *MATRIX_RELT(origin, 2, 1) = (mri->height - 1.0) / 2.0;
10845   *MATRIX_RELT(origin, 3, 1) = (mri->depth  - 1.0) / 2.0;
10846   *MATRIX_RELT(origin, 4, 1) = 1.0;
10847 
10848   c = MatrixMultiply(m, origin, NULL);
10849   if(c == NULL)
10850     {
10851       MatrixFree(&origin);
10852       ErrorReturn
10853         (ERROR_BADPARM,
10854          (ERROR_BADPARM,
10855           "apply_i_to_r(): error multiplying matrices"));
10856     }
10857 
10858   mri->c_r = *MATRIX_RELT(c, 1, 1);
10859   mri->c_a = *MATRIX_RELT(c, 2, 1);
10860   mri->c_s = *MATRIX_RELT(c, 3, 1);
10861 
10862   MatrixFree(&origin);
10863   MatrixFree(&c);
10864 
10865   mri->ras_good_flag = 1;
10866 
10867   return(NO_ERROR);
10868 
10869 } /* end apply_i_to_r() */
10870 
10871 MATRIX *
10872 MRIrasXformToVoxelXform(MRI *mri_src, MRI *mri_dst, MATRIX *m_ras_xform,
10873                         MATRIX *m_voxel_xform)
10874 {
10875   MATRIX *m_ras_to_voxel, *m_voxel_to_ras, *m_tmp ;
10876 
10877   if (!mri_dst)
10878     mri_dst = mri_src ;   /* assume they will be in the same space */
10879 
10880   m_voxel_to_ras = MRIgetVoxelToRasXform(mri_src) ;
10881   m_ras_to_voxel = MRIgetRasToVoxelXform(mri_dst) ;
10882 
10883   m_tmp = MatrixMultiply(m_ras_xform, m_voxel_to_ras, NULL) ;
10884   m_voxel_xform = MatrixMultiply(m_ras_to_voxel, m_tmp, m_voxel_xform) ;
10885 
10886   MatrixFree(&m_voxel_to_ras); MatrixFree(&m_ras_to_voxel); MatrixFree(&m_tmp);
10887 
10888   return(m_voxel_xform) ;
10889 }
10890 
10891 MATRIX *
10892 MRIvoxelXformToRasXform(MRI *mri_src, MRI *mri_dst, MATRIX *m_voxel_xform,
10893                         MATRIX *m_ras_xform)
10894 {
10895   MATRIX *m_ras_to_voxel, *m_voxel_to_ras, *m_tmp ;
10896 
10897   if (!mri_dst)
10898     mri_dst = mri_src ;  /* assume they will be in the same space */
10899 
10900   m_ras_to_voxel = MRIgetRasToVoxelXform(mri_src) ;
10901   m_voxel_to_ras = MRIgetVoxelToRasXform(mri_dst) ;
10902 
10903   m_tmp = MatrixMultiply(m_voxel_xform, m_ras_to_voxel, NULL) ;
10904   m_ras_xform = MatrixMultiply(m_voxel_to_ras, m_tmp, m_ras_xform) ;
10905 
10906   MatrixFree(&m_voxel_to_ras); MatrixFree(&m_ras_to_voxel); MatrixFree(&m_tmp);
10907 
10908   return(m_ras_xform) ;
10909 }
10910 
10911 MATRIX *extract_r_to_i(MRI *mri)
10912 {
10913   MATRIX *m_ras_to_voxel, *m_voxel_to_ras ;
10914 
10915   m_voxel_to_ras = extract_i_to_r(mri) ;
10916   m_ras_to_voxel = MatrixInverse(m_voxel_to_ras, NULL) ;
10917   MatrixFree(&m_voxel_to_ras) ;
10918   return(m_ras_to_voxel) ;
10919 }
10920 
10921 int
10922 MRIsetVoxelToRasXform(MRI *mri, MATRIX *m_vox2ras)
10923 {
10924   float ci, cj, ck;
10925 
10926   mri->x_r = *MATRIX_RELT(m_vox2ras, 1, 1) / mri->xsize ;
10927   mri->y_r = *MATRIX_RELT(m_vox2ras, 1, 2) / mri->ysize ;
10928   mri->z_r = *MATRIX_RELT(m_vox2ras, 1, 3) / mri->zsize ;
10929 
10930   mri->x_a = *MATRIX_RELT(m_vox2ras, 2, 1) / mri->xsize ;
10931   mri->y_a = *MATRIX_RELT(m_vox2ras, 2, 2) / mri->ysize ;
10932   mri->z_a = *MATRIX_RELT(m_vox2ras, 2, 3) / mri->zsize ;
10933 
10934   mri->x_s = *MATRIX_RELT(m_vox2ras, 3, 1) / mri->xsize ;
10935   mri->y_s = *MATRIX_RELT(m_vox2ras, 3, 2) / mri->ysize ;
10936   mri->z_s = *MATRIX_RELT(m_vox2ras, 3, 3) / mri->zsize ;
10937 
10938   ci = (mri->width) / 2.0;
10939   cj = (mri->height) / 2.0;
10940   ck = (mri->depth) / 2.0;
10941   mri->c_r = *MATRIX_RELT(m_vox2ras, 1, 4) +
10942     (*MATRIX_RELT(m_vox2ras, 1, 1) * ci +
10943      *MATRIX_RELT(m_vox2ras, 1, 2) * cj +
10944      *MATRIX_RELT(m_vox2ras, 1, 3) * ck);
10945   mri->c_a = *MATRIX_RELT(m_vox2ras, 2, 4) +
10946     (*MATRIX_RELT(m_vox2ras, 2, 1) * ci +
10947      *MATRIX_RELT(m_vox2ras, 2, 2) * cj +
10948      *MATRIX_RELT(m_vox2ras, 2, 3) * ck);
10949   mri->c_s = *MATRIX_RELT(m_vox2ras, 3, 4) +
10950     (*MATRIX_RELT(m_vox2ras, 3, 1) * ci +
10951      *MATRIX_RELT(m_vox2ras, 3, 2) * cj +
10952      *MATRIX_RELT(m_vox2ras, 3, 3) * ck);
10953   MRIreInitCache(mri);
10954   return(NO_ERROR) ;
10955 }
10956 
10957 // allocate memory and the user must free it.
10958 MATRIX *extract_i_to_r(MRI *mri)
10959 {
10960   MATRIX *m;
10961   float m11, m12, m13, m14;
10962   float m21, m22, m23, m24;
10963   float m31, m32, m33, m34;
10964   float ci, cj, ck;
10965 
10966   m = MatrixAlloc(4, 4, MATRIX_REAL);
10967   if(m == NULL)
10968     {
10969       ErrorReturn
10970         (NULL,
10971          (ERROR_BADPARM,
10972           "extract_i_to_r(): error allocating matrix"));
10973     }
10974 
10975   m11 = mri->xsize * mri->x_r;
10976   m12 = mri->ysize * mri->y_r;
10977   m13 = mri->zsize * mri->z_r;
10978   m21 = mri->xsize * mri->x_a;
10979   m22 = mri->ysize * mri->y_a;
10980   m23 = mri->zsize * mri->z_a;
10981   m31 = mri->xsize * mri->x_s;
10982   m32 = mri->ysize * mri->y_s;
10983   m33 = mri->zsize * mri->z_s;
10984 
10985   ci = (mri->width) / 2.0;
10986   cj = (mri->height) / 2.0;
10987   ck = (mri->depth) / 2.0;
10988 
10989   m14 = mri->c_r - (m11 * ci + m12 * cj + m13 * ck);
10990   m24 = mri->c_a - (m21 * ci + m22 * cj + m23 * ck);
10991   m34 = mri->c_s - (m31 * ci + m32 * cj + m33 * ck);
10992 
10993   stuff_four_by_four(m, m11, m12, m13, m14,
10994                      m21, m22, m23, m24,
10995                      m31, m32, m33, m34,
10996                      0.0, 0.0, 0.0, 1.0);
10997 
10998 
10999   return(m);
11000 
11001 } /* end extract_i_to_r() */
11002 
11003 /* eof */
11004 MRI *
11005 MRIscaleMeanIntensities(MRI *mri_src, MRI *mri_ref, MRI *mri_dst)
11006 {
11007   int    width, height, depth, x, y, z, val ;
11008   double ref_mean, src_mean, nref_vox, nsrc_vox, scale ;
11009 
11010   mri_dst = MRIcopy(mri_src, mri_dst) ;
11011 
11012   width = mri_dst->width ; height = mri_dst->height ; depth = mri_dst->depth;
11013 
11014   nref_vox = nsrc_vox = src_mean = ref_mean = 0.0 ;
11015   for (z = 0 ; z < depth ; z++)
11016     {
11017       for (y = 0 ; y < height ; y++)
11018         {
11019           for (x = 0 ; x < width ; x++)
11020             {
11021               if (MRIvox(mri_ref,x,y,z) > 10)
11022                 {
11023                   nref_vox++ ;
11024                   ref_mean += (double)MRIvox(mri_ref, x, y, z) ;
11025                 }
11026               if (MRIvox(mri_src,x,y,z) > 10)
11027                 {
11028                   src_mean += (double)MRIvox(mri_src, x, y, z) ;
11029                   nsrc_vox++ ;
11030                 }
11031             }
11032         }
11033     }
11034 
11035   ref_mean /= nref_vox ; src_mean /= nsrc_vox ;
11036   fprintf(stderr, "mean brightnesses: ref = %2.1f, in = %2.1f\n",
11037           ref_mean, src_mean) ;
11038   scale = ref_mean / src_mean ;
11039   for (z = 0 ; z < depth ; z++)
11040     {
11041       for (y = 0 ; y < height ; y++)
11042         {
11043           for (x = 0 ; x < width ; x++)
11044             {
11045               val = MRIvox(mri_src, x, y, z) ;
11046               val = nint(val*scale) ;
11047               if (val > 255)
11048                 val = 255 ;
11049               MRIvox(mri_src, x, y, z) = val ;
11050             }
11051         }
11052     }
11053 
11054   return(mri_dst) ;
11055 }
11056 
11057 MRI *MRIsmoothParcellation(MRI *mri, int smooth_parcellation_count)
11058 {
11059 
11060   MRI *mri2;
11061   int i, j, k;
11062   short vals[26];
11063   int counts[32768];
11064   int c;
11065 
11066   if(mri->type != MRI_SHORT)
11067     {
11068       ErrorReturn
11069         (NULL,
11070          (ERROR_UNSUPPORTED,
11071           "MRIsmoothParcellation(): only supported for shorts data"));
11072     }
11073 
11074   mri2 = MRIcopy(mri, NULL);
11075   if(mri2 == NULL)
11076     {
11077       ErrorReturn
11078         (NULL,
11079          (ERROR_NOMEMORY,
11080           "MRIsmoothParcellation(): error copying structre"));
11081     }
11082 
11083   for(i = 1;i < mri->width-1;i++)
11084     {
11085       for(j = 1;j < mri->height-1;j++)
11086         {
11087           for(k = 1;k < mri->depth-1;k++)
11088             {
11089 
11090               memset(counts, 0x00, 32768 * sizeof(int));
11091 
11092               vals[ 0] = MRISvox(mri, i+1, j+1, k+1);
11093               vals[ 1] = MRISvox(mri, i+1, j+1, k  );
11094               vals[ 2] = MRISvox(mri, i+1, j+1, k-1);
11095               vals[ 3] = MRISvox(mri, i+1, j  , k+1);
11096               vals[ 4] = MRISvox(mri, i+1, j  , k  );
11097               vals[ 5] = MRISvox(mri, i+1, j  , k-1);
11098               vals[ 6] = MRISvox(mri, i+1, j-1, k+1);
11099               vals[ 7] = MRISvox(mri, i+1, j-1, k  );
11100               vals[ 8] = MRISvox(mri, i+1, j-1, k-1);
11101 
11102               vals[ 9] = MRISvox(mri, i  , j+1, k+1);
11103               vals[10] = MRISvox(mri, i  , j+1, k  );
11104               vals[11] = MRISvox(mri, i  , j+1, k-1);
11105               vals[12] = MRISvox(mri, i  , j  , k+1);
11106               /* --- ignore the voxel itself --- */
11107               vals[13] = MRISvox(mri, i  , j  , k-1);
11108               vals[14] = MRISvox(mri, i  , j-1, k+1);
11109               vals[15] = MRISvox(mri, i  , j-1, k  );
11110               vals[16] = MRISvox(mri, i  , j-1, k-1);
11111 
11112               vals[17] = MRISvox(mri, i-1, j+1, k+1);
11113               vals[18] = MRISvox(mri, i-1, j+1, k  );
11114               vals[19] = MRISvox(mri, i-1, j+1, k-1);
11115               vals[20] = MRISvox(mri, i-1, j  , k+1);
11116               vals[21] = MRISvox(mri, i-1, j  , k  );
11117               vals[22] = MRISvox(mri, i-1, j  , k-1);
11118               vals[23] = MRISvox(mri, i-1, j-1, k+1);
11119               vals[24] = MRISvox(mri, i-1, j-1, k  );
11120               vals[25] = MRISvox(mri, i-1, j-1, k-1);
11121 
11122               for(c = 0;c < 26;c++)
11123                 counts[vals[c]]++;
11124 
11125               for(c = 0;c < 26;c++)
11126                 if(counts[vals[c]] >= smooth_parcellation_count)
11127                   MRISvox(mri2, i, j, k) = vals[c];
11128 
11129             }
11130         }
11131     }
11132 
11133   return(mri2);
11134 
11135 } /* end MRIsmoothParcellation() */
11136 
11137 int
11138 MRIeraseBorderPlanes(MRI *mri)
11139 {
11140   int  x, y, z ;
11141 
11142   for (x = 0 ; x < mri->width ; x++)
11143     for (y = 0 ; y < mri->height ; y++)
11144       {
11145         MRIvox(mri, x, y, 0) = MRIvox(mri, x, y, mri->depth-1) = 0 ;
11146       }
11147 
11148   for (y = 0 ; y < mri->height ; y++)
11149     for (z = 0 ; z < mri->depth ; z++)
11150       {
11151         MRIvox(mri, 0, y, z) = MRIvox(mri, mri->width-1, y, z) = 0 ;
11152       }
11153 
11154   for (x = 0 ; x < mri->width ; x++)
11155     for (z = 0 ; z < mri->depth ; z++)
11156       {
11157         MRIvox(mri, x, 0, z) = MRIvox(mri, x, mri->height-1, z) = 0 ;
11158       }
11159 
11160   return(NO_ERROR) ;
11161 }
11162 int
11163 MRIcopyPulseParameters(MRI *mri_src, MRI *mri_dst)
11164 {
11165   mri_dst->flip_angle = mri_src->flip_angle ;
11166   mri_dst->tr = mri_src->tr ;
11167   mri_dst->te = mri_src->te ;
11168   mri_dst->ti = mri_src->ti ;
11169   return(NO_ERROR) ;
11170 }
11171 float
11172 MRIfindNearestNonzero(MRI *mri, int wsize, Real xr, Real yr, Real zr)
11173 {
11174   int   xk, yk, zk, xi, yi, zi, whalf, x, y, z ;
11175   float dist, min_dist, min_val, dx, dy, dz ;
11176 
11177   x = mri->xi[nint(xr)] ; y = mri->yi[nint(yr)] ; z = mri->zi[nint(zr)] ;
11178   if (MRIvox(mri, x, y, z) > 0)
11179     return((float)MRIvox(mri, x, y, z)) ;
11180 
11181   min_dist = 100000 ; min_val = 0 ;
11182   whalf = (wsize-1)/2 ;
11183   for (zk = -whalf ; zk <= whalf ; zk++)
11184     {
11185       zi = mri->zi[z+zk] ;
11186       dz = zi-zr ;
11187       for (yk = -whalf ; yk <= whalf ; yk++)
11188         {
11189           yi = mri->yi[y+yk] ;
11190           dy = yi-yr ;
11191           for (xk = -whalf ; xk <= whalf ; xk++)
11192             {
11193               xi = mri->xi[x+xk] ;
11194               dx = xi-xr ;
11195               if (MRIgetVoxVal(mri, xi, yi, zi,0) > 0)
11196                 {
11197                   dist = sqrt(dx*dx + dy*dy + dz*dz) ;
11198                   if (dist < min_dist)
11199                     {
11200                       min_dist = dist ;
11201                       min_val = MRIgetVoxVal(mri, xi, yi, zi,0) ;
11202                     }
11203                 }
11204             }
11205         }
11206     }
11207   return(min_val) ;
11208 }
11209 int
11210 MRIcountNonzeroInNbhd(MRI *mri, int wsize, int x, int y, int z)
11211 {
11212   int   xk, yk, zk, xi, yi, zi, whalf, total ;
11213 
11214   whalf = (wsize-1)/2 ;
11215   for (total = 0, zk = -whalf ; zk <= whalf ; zk++)
11216     {
11217       zi = mri->zi[z+zk] ;
11218       for (yk = -whalf ; yk <= whalf ; yk++)
11219         {
11220           yi = mri->yi[y+yk] ;
11221           for (xk = -whalf ; xk <= whalf ; xk++)
11222             {
11223               xi = mri->xi[x+xk] ;
11224               if (MRIgetVoxVal(mri, xi, yi, zi,0) > 0)
11225                 total++ ;
11226             }
11227         }
11228     }
11229   return(total) ;
11230 }
11231 int
11232 MRIareNonzeroInNbhd(MRI *mri, int wsize, int x, int y, int z)
11233 {
11234   int   xk, yk, zk, xi, yi, zi, whalf ;
11235 
11236   whalf = (wsize-1)/2 ;
11237   for (zk = -whalf ; zk <= whalf ; zk++)
11238     {
11239       zi = mri->zi[z+zk] ;
11240       for (yk = -whalf ; yk <= whalf ; yk++)
11241         {
11242           yi = mri->yi[y+yk] ;
11243           for (xk = -whalf ; xk <= whalf ; xk++)
11244             {
11245               xi = mri->xi[x+xk] ;
11246               if (MRIgetVoxVal(mri, xi, yi, zi,0) > 0)
11247                 return(1) ;
11248             }
11249         }
11250     }
11251   return(0) ;
11252 }
11253 float
11254 MRIfindNearestNonzeroLocation(MRI *mri, int wsize, Real xr, Real yr, Real zr,
11255                               int *pxv, int *pyv, int *pzv)
11256 {
11257   int   xk, yk, zk, xi, yi, zi, whalf, x, y, z ;
11258   float dist, min_dist, min_val, dx, dy, dz ;
11259 
11260   x = nint(xr) ; y = nint(yr) ; z = nint(zr) ;
11261   if (MRIvox(mri, x, y, z) > 0)
11262     return((float)MRIvox(mri, x, y, z)) ;
11263 
11264   min_dist = 100000 ; min_val = 0 ;
11265   whalf = (wsize-1)/2 ;
11266   for (zk = -whalf ; zk <= whalf ; zk++)
11267     {
11268       zi = mri->zi[z+zk] ;
11269       dz = zi-zr ;
11270       for (yk = -whalf ; yk <= whalf ; yk++)
11271         {
11272           yi = mri->yi[y+yk] ;
11273           dy = yi-yr ;
11274           for (xk = -whalf ; xk <= whalf ; xk++)
11275             {
11276               xi = mri->xi[x+xk] ;
11277               dx = xi-xr ;
11278               if (MRIvox(mri, xi, yi, zi) > 0)
11279                 {
11280                   dist = sqrt(dx*dx + dy*dy + dz*dz) ;
11281                   if (dist < min_dist)
11282                     {
11283                       if (pxv)
11284                         { *pxv = xi ; *pyv = yi ; *pzv = zi ;}
11285                       min_dist = dist ;
11286                       min_val = MRIvox(mri, xi, yi, zi) ;
11287                     }
11288                 }
11289             }
11290         }
11291     }
11292   return(min_val) ;
11293 }
11294 
11295 MRI *
11296 MRIfromTalairach(MRI *mri_src, MRI *mri_dst)
11297 {
11298   int  x, y, z, xv, yv, zv ;
11299   Real xt, yt, zt, xn, yn, zn, val ;
11300 
11301   if (!mri_dst)
11302     mri_dst = MRIclone(mri_src, NULL) ;
11303 
11304   for (x = 0 ; x < mri_dst->width ; x++)
11305     {
11306       xn = (Real)x ;
11307       for (y = 0 ; y < mri_dst->height ; y++)
11308         {
11309           yn = (Real)y ;
11310           for (z = 0 ; z < mri_dst->depth ; z++)
11311             {
11312               zn = (Real)z ;
11313               MRIvoxelToTalairachVoxel(mri_src, xn, yn, zn, &xt, &yt, &zt) ;
11314               xv = nint(xt) ; yv = nint(yt) ; zv = nint(zt) ;
11315               if ((xv >= 0 && xv < mri_src->width) &&
11316                   (yv >= 0 && yv < mri_src->height) &&
11317                   (zv >= 0 && zv < mri_src->depth))
11318                 {
11319                   MRIsampleVolume(mri_src, xt, yt, zt, &val) ;
11320                   MRIvox(mri_dst, x, y, z) = val ;
11321                 }
11322               else
11323                 MRIvox(mri_dst, x, y, z) = 0 ;
11324             }
11325         }
11326     }
11327 
11328   return(mri_dst) ;
11329 }
11330 MRI *
11331 MRItoTalairach(MRI *mri_src, MRI *mri_dst)
11332 {
11333   int  x, y, z, xv, yv, zv ;
11334   Real xt, yt, zt, xn, yn, zn, val ;
11335 
11336   if (!mri_dst)
11337     mri_dst = MRIclone(mri_src, NULL) ;
11338 
11339   for (x = 0 ; x < mri_dst->width ; x++)
11340     {
11341       xt = (Real)x ;
11342       for (y = 0 ; y < mri_dst->height ; y++)
11343         {
11344           yt = (Real)y ;
11345           for (z = 0 ; z < mri_dst->depth ; z++)
11346             {
11347               zt = (Real)z ;
11348               MRItalairachVoxelToVoxel(mri_src, xt, yt, zt, &xn, &yn, &zn) ;
11349               xv = nint(xn) ; yv = nint(yn) ; zv = nint(zt) ;
11350               if ((xv >= 0 && xv < mri_src->width) &&
11351                   (yv >= 0 && yv < mri_src->height) &&
11352                   (zv >= 0 && zv < mri_src->depth))
11353                 {
11354                   MRIsampleVolume(mri_src, xn, yn, zn, &val) ;
11355                   MRIvox(mri_dst, x, y, z) = val ;
11356                 }
11357               else
11358                 MRIvox(mri_dst, x, y, z) = 0 ;
11359             }
11360         }
11361     }
11362 
11363   return(mri_dst) ;
11364 }
11365 /*-------------------------------------------------------------------
11366   MRIlog10() - computes the log10 of the values at each voxel and
11367   frame. If a value is zero, the result is set to 10000000000.0. If
11368   the negflag is set, then -log10 is computed. The result is stored
11369   in outmri. If outmri is NULL, the output MRI is alloced and its
11370   pointer returned.
11371   ------------------------------------------------------------------*/
11372 MRI *MRIlog10(MRI *inmri, MRI *outmri, int negflag)
11373 {
11374   int c, r, s, f;
11375   float val;
11376 
11377   if(outmri==NULL){
11378     outmri = MRIallocSequence(inmri->width, inmri->height, inmri->depth,
11379                               MRI_FLOAT, inmri->nframes);
11380     MRIcopyHeader(inmri,outmri);
11381 
11382     if(outmri==NULL){
11383       printf("ERROR: fMRIlog10: could not alloc\n");
11384       return(NULL);
11385     }
11386   }
11387   else{
11388     if(inmri->width   != outmri->width  ||
11389        inmri->height  != outmri->height ||
11390        inmri->depth   != outmri->depth  ||
11391        inmri->nframes != outmri->nframes){
11392       printf("ERROR: MRIlog10: output dimension mismatch\n");
11393       return(NULL);
11394     }
11395     if(outmri->type != MRI_FLOAT){
11396       printf("ERROR: MRIlog10: structure passed is not MRI_FLOAT\n");
11397       return(NULL);
11398     }
11399   }
11400 
11401   for(c=0; c < inmri->width; c++){
11402     for(r=0; r < inmri->height; r++){
11403       for(s=0; s < inmri->depth; s++){
11404         for(f=0; f < inmri->nframes; f++){
11405           val = MRIgetVoxVal(inmri, c, r, s, f);
11406           if(val == 0)     MRIFseq_vox(outmri,c,r,s,f) = 10000000000.0;
11407           else{
11408             if(negflag){
11409               if(val < 0) MRIFseq_vox(outmri,c,r,s,f) =  log10(fabs(val));
11410               else        MRIFseq_vox(outmri,c,r,s,f) = -log10(val);
11411             }
11412             else{
11413               if(val < 0) MRIFseq_vox(outmri,c,r,s,f) = -log10(fabs(val));
11414               else        MRIFseq_vox(outmri,c,r,s,f) =  log10(val);
11415             }
11416           }
11417         }
11418       }
11419     }
11420   }
11421 
11422   return(outmri);
11423 }
11424 /*---------------------------------------------------------------------
11425   MRIrandn() - fills an MRI structure with values sampled from a
11426   normal distribution with mean avg and standard devation stddev.
11427   --------------------------------------------------------*/
11428 MRI *MRIrandn(int ncols, int nrows, int nslices, int nframes,
11429               float avg, float stddev, MRI *mri)
11430 {
11431   int c, r, s, f;
11432 
11433   if(mri==NULL){
11434     mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11435     if(mri==NULL){
11436       printf("ERROR: MRIrandn: could not alloc\n");
11437       return(NULL);
11438     }
11439   }
11440   else{
11441     if(mri->width != ncols   || mri->height != nrows ||
11442        mri->depth != nslices || mri->nframes != nframes){
11443       printf("ERROR: MRIrandn: dimension mismatch\n");
11444       return(NULL);
11445     }
11446     if(mri->type != MRI_FLOAT){
11447       printf("ERROR: MRIrandn: structure passed is not MRI_FLOAT\n");
11448       return(NULL);
11449     }
11450   }
11451 
11452   for(f=0; f<nframes; f++){
11453     for(s=0; s<nslices; s++){
11454       for(r=0; r<nrows; r++){
11455         for(c=0; c<ncols; c++){
11456           MRIFseq_vox(mri,c,r,s,f) =
11457             stddev*PDFgaussian() + avg;
11458         }
11459       }
11460     }
11461   }
11462 
11463   return(mri);
11464 }
11465 /*---------------------------------------------------------------------
11466   MRIrande() - fills an MRI structure with values sampled from an
11467   Erlang distribution with mean avg and order order. The variance
11468   will be (avg^2)/order. Theoretical distribution is
11469   r = order
11470   pdf(x) = r*((r*(x-avg+1))^(r-1)) * exp(-r*(x-avg+1)) / (r-1)!
11471   when order=1, this generates an exponential distribution.
11472   --------------------------------------------------------*/
11473 MRI *MRIrande(int ncols, int nrows, int nslices, int nframes,
11474               float avg, int order, MRI *mri)
11475 {
11476   int c, r, s, f;
11477 
11478   if(mri==NULL){
11479     mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11480     if(mri==NULL){
11481       printf("ERROR: MRIrande: could not alloc\n");
11482       return(NULL);
11483     }
11484   }
11485   else{
11486     if(mri->width != ncols   || mri->height != nrows ||
11487        mri->depth != nslices || mri->nframes != nframes){
11488       printf("ERROR: MRIrande: dimension mismatch\n");
11489       return(NULL);
11490     }
11491     if(mri->type != MRI_FLOAT){
11492       printf("ERROR: MRIrande: structure passed is not MRI_FLOAT\n");
11493       return(NULL);
11494     }
11495   }
11496 
11497   avg = avg - 1; // PDFrande() already has average of 1
11498   for(f=0; f<nframes; f++){
11499     for(s=0; s<nslices; s++){
11500       for(r=0; r<nrows; r++){
11501         for(c=0; c<ncols; c++){
11502           MRIFseq_vox(mri,c,r,s,f) =
11503             PDFerlang(order) + avg;
11504         }
11505       }
11506     }
11507   }
11508 
11509   return(mri);
11510 }
11511 /*---------------------------------------------------------------------
11512   MRIdrand48() - fills an MRI structure with values sampled from a
11513   the drand48 uniform random number generator. The user must specify
11514   the min and max. Note: the stddev = (max-min)*0.289. If mri is NULL,
11515   it will alloc a MRI_FLOAT volume, otherwise, it will use the type
11516   as specified in mri.
11517   --------------------------------------------------------*/
11518 MRI *MRIdrand48(int ncols, int nrows, int nslices, int nframes,
11519                 float min, float max, MRI *mri)
11520 {
11521   int c, r, s, f, n;
11522   float range, v;
11523   BUFTYPE *pmri=NULL;
11524   short   *psmri=NULL;
11525   int     *pimri=NULL;
11526   long    *plmri=NULL;
11527   float   *pfmri=NULL;
11528 
11529   if(mri==NULL){
11530     mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11531     if(mri==NULL){
11532       printf("ERROR: MRIdrand48: could not alloc\n");
11533       return(NULL);
11534     }
11535   }
11536   else{
11537     if(mri->width != ncols   || mri->height != nrows ||
11538        mri->depth != nslices || mri->nframes != nframes){
11539       printf("ERROR: MRIdrand48: dimension mismatch\n");
11540       return(NULL);
11541     }
11542   }
11543 
11544   range = max-min;
11545   n = 0;
11546   for(f=0; f<nframes; f++){
11547     for(s=0; s<nslices; s++){
11548       for(r=0; r<nrows; r++){
11549         switch(mri->type){
11550         case MRI_UCHAR: pmri  =           mri->slices[n][r]; break;
11551         case MRI_SHORT: psmri = (short *) mri->slices[n][r]; break;
11552         case MRI_INT:   pimri = (int *)   mri->slices[n][r]; break;
11553         case MRI_LONG:  plmri = (long *)  mri->slices[n][r]; break;
11554         case MRI_FLOAT: pfmri = (float *) mri->slices[n][r]; break;
11555         }
11556         for(c=0; c<ncols; c++) {
11557           v = range*drand48() + min;
11558           switch(mri->type){
11559           case MRI_UCHAR: *pmri++  = (BUFTYPE) v; break;
11560           case MRI_SHORT: *psmri++ = (short) v; break;
11561           case MRI_INT:   *pimri++ = (int)   v; break;
11562           case MRI_LONG:  *plmri++ = (long)  v; break;
11563           case MRI_FLOAT: *pfmri++ = (float) v; break;
11564           }
11565         }
11566       }
11567       n++;
11568     }
11569   }
11570 
11571   return(mri);
11572 }
11573 /*---------------------------------------------------------------------
11574   MRIsampleCDF() - fills an MRI structure with values sampled from a
11575   the given CDF. See PDFsampleCDF(). CDF[n] is the probability that
11576   the random number is <= xCDF[n].
11577   --------------------------------------------------------------------*/
11578 MRI *MRIsampleCDF(int ncols, int nrows, int nslices, int nframes,
11579                   double *xCDF, double *CDF, int nCDF, MRI *mri)
11580 {
11581   int c, r, s, f;
11582 
11583   if(mri==NULL){
11584     mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11585     if(mri==NULL){
11586       printf("ERROR: MRIsampleCDF: could not alloc\n");
11587       return(NULL);
11588     }
11589   }
11590   else{
11591     if(mri->width != ncols   || mri->height != nrows ||
11592        mri->depth != nslices || mri->nframes != nframes){
11593       printf("ERROR: MRIsampleCDF: dimension mismatch\n");
11594       return(NULL);
11595     }
11596     if(mri->type != MRI_FLOAT){
11597       printf("ERROR: MRIsampleCDF: structure passed is not MRI_FLOAT\n");
11598       return(NULL);
11599     }
11600   }
11601 
11602   for(f=0; f<nframes; f++){
11603     for(s=0; s<nslices; s++){
11604       for(r=0; r<nrows; r++){
11605         for(c=0; c<ncols; c++){
11606           MRIFseq_vox(mri,c,r,s,f) = PDFsampleCDF(xCDF,CDF,nCDF);
11607         }
11608       }
11609     }
11610   }
11611 
11612   return(mri);
11613 }
11614 /*---------------------------------------------------------------------
11615   MRIconst() - fills an MRI structure with the given value. If mri is
11616   NULL, it will alloc a MRI_FLOAT volume, otherwise, it will use the type
11617   as specified in mri.
11618   --------------------------------------------------------*/
11619 MRI *MRIconst(int ncols, int nrows, int nslices, int nframes,
11620               float val, MRI *mri)
11621 {
11622   int c, r, s, f, n;
11623   BUFTYPE *pmri=NULL;
11624   short   *psmri=NULL;
11625   int     *pimri=NULL;
11626   long    *plmri=NULL;
11627   float   *pfmri=NULL;
11628 
11629   if(mri==NULL){
11630     mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11631     if(mri==NULL){
11632       printf("ERROR: MRIdconst: could not alloc\n");
11633       return(NULL);
11634     }
11635   }
11636   else{
11637     if(mri->width != ncols   || mri->height != nrows ||
11638        mri->depth != nslices || mri->nframes != nframes){
11639       printf("ERROR: MRIconst: dimension mismatch\n");
11640       return(NULL);
11641     }
11642   }
11643 
11644   n = 0;
11645   for(f=0; f<nframes; f++){
11646     for(s=0; s<nslices; s++){
11647       for(r=0; r<nrows; r++){
11648         switch(mri->type){
11649         case MRI_UCHAR: pmri  =           mri->slices[n][r]; break;
11650         case MRI_SHORT: psmri = (short *) mri->slices[n][r]; break;
11651         case MRI_INT:   pimri = (int *)   mri->slices[n][r]; break;
11652         case MRI_LONG:  plmri = (long *)  mri->slices[n][r]; break;
11653         case MRI_FLOAT: pfmri = (float *) mri->slices[n][r]; break;
11654         }
11655         for(c=0; c<ncols; c++) {
11656           switch(mri->type){
11657           case MRI_UCHAR: *pmri++  = (BUFTYPE) val; break;
11658           case MRI_SHORT: *psmri++ = (short) val; break;
11659           case MRI_INT:   *pimri++ = (int)   val; break;
11660           case MRI_LONG:  *plmri++ = (long)  val; break;
11661           case MRI_FLOAT: *pfmri++ = (float) val; break;
11662           }
11663         }
11664       }
11665       n++;
11666     }
11667   }
11668 
11669   return(mri);
11670 }
11671 /*--------------------------------------------------------------*/
11672 
11673 int
11674 MRInormalizeSequence(MRI *mri, float target)
11675 {
11676   int    x, y, z, frame ;
11677   double norm ;
11678   Real   val ;
11679 
11680   for (x = 0 ; x < mri->width ; x++)
11681     {
11682       for (y = 0 ; y < mri->height ; y++)
11683         {
11684           for (z = 0 ; z < mri->depth ; z++)
11685             {
11686               for (frame = 0, norm = 0 ; frame < mri->nframes ; frame++)
11687                 {
11688                   MRIsampleVolumeFrame(mri, x, y, z, frame, &val) ;
11689                   norm += (val*val) ;
11690                 }
11691               norm = sqrt(norm) / target ;
11692               if (FZERO(norm))
11693                 norm = 1 ;
11694               for (frame = 0 ; frame < mri->nframes ; frame++)
11695                 {
11696                   switch (mri->type)
11697                     {
11698                     default:
11699                       ErrorReturn
11700                         (ERROR_UNSUPPORTED,
11701                          (ERROR_UNSUPPORTED,
11702                           "MRInormalizeSequence: unsupported input type %d",
11703                           mri->type)) ;
11704                       break ;
11705                     case MRI_SHORT:
11706                       MRISseq_vox(mri, x, y, z, frame) =
11707                         MRISseq_vox(mri, x, y, z, frame) / norm ;
11708                       break ;
11709                     case MRI_FLOAT:
11710                       MRIFseq_vox(mri, x, y, z, frame) /= norm ;
11711                       break ;
11712                     case MRI_UCHAR:
11713                       MRIseq_vox(mri, x, y, z, frame) /= norm ;
11714                       break ;
11715                     }
11716                 }
11717             }
11718         }
11719     }
11720 
11721   return(NO_ERROR) ;
11722 }
11723 
11724 double
11725 MRImeanInLabel(MRI *mri_src, MRI *mri_labeled, int label)
11726 {
11727   int  x, y, z, nvox, l ;
11728   double mean = 0.0 ;
11729   float  val ;
11730 
11731   nvox = 0 ;
11732   for (x = 0 ; x < mri_src->width ; x++)
11733     {
11734       for (y = 0 ; y < mri_src->height ; y++)
11735         {
11736           for (z = 0 ; z < mri_src->depth ; z++)
11737             {
11738               l = nint(MRIgetVoxVal(mri_labeled, x, y, z, 0)) ;
11739               if (l == label)
11740                 {
11741                   val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
11742                   mean += val ;
11743                   nvox++ ;
11744                 }
11745             }
11746         }
11747     }
11748   if (!nvox)
11749     nvox = 1 ;
11750   return(mean/nvox) ;
11751 }
11752 
11753 MRI *
11754 MRImakePositive(MRI *mri_src, MRI *mri_dst)
11755 {
11756   float   fmin, fmax, val ;
11757   int     x, y, z,f  ;
11758 
11759   MRIvalRange(mri_src, &fmin, &fmax) ;
11760   mri_dst = MRIcopy(mri_src, mri_dst) ;
11761   if (fmin >= 0)
11762     return(mri_dst) ;
11763 
11764   for (f = 0 ; f < mri_dst->nframes ; f++)
11765     {
11766       for (x = 0 ; x < mri_dst->width ; x++)
11767         {
11768           for (y = 0 ; y < mri_dst->height ; y++)
11769             {
11770               for (z = 0 ; z < mri_dst->depth ; z++)
11771                 {
11772                   val = MRIgetVoxVal(mri_src, x, y, z, f) ;
11773                   val -= fmin ;
11774                   MRIsetVoxVal(mri_dst, x, y, z, f, val) ;
11775                 }
11776             }
11777         }
11778     }
11779 
11780   return(mri_dst) ;
11781 }
11782 MRI *
11783 MRIeraseNegative(MRI *mri_src, MRI *mri_dst)
11784 {
11785   int  x, y, z ;
11786   float  val ;
11787 
11788   mri_dst = MRIcopy(mri_src, mri_dst) ;
11789 
11790   for (x = 0 ; x < mri_src->width ; x++)
11791     {
11792       for (y = 0 ; y < mri_src->height ; y++)
11793         {
11794           for (z = 0 ; z < mri_src->depth ; z++)
11795             {
11796               val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
11797               if (val < 0)
11798                 MRIsetVoxVal(mri_dst, x, y, z, 0, 0) ;
11799             }
11800         }
11801     }
11802   return(mri_dst) ;
11803 }
11804 int
11805 MRIsampleVolumeSlice
11806 (MRI *mri, Real x, Real y, Real z, Real *pval, int slice_direction)
11807 {
11808   int  OutOfBounds;
11809   int  xm, xp, ym, yp, zm, zp, width, height, depth ;
11810   Real val, xmd, ymd, xpd, ypd ;  /* d's are distances */
11811   Real val11, val12, val21, val22 ;
11812 
11813   if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
11814     return(MRIsampleVolumeType(mri, x, y, z, pval, SAMPLE_NEAREST)) ;
11815 
11816   OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
11817   if(OutOfBounds == 1){
11818     /* unambiguously out of bounds */
11819     *pval = 0.0;
11820     return(NO_ERROR) ;
11821   }
11822 
11823   width = mri->width ; height = mri->height ; depth = mri->depth ;
11824 
11825   if (x >= width)    x = width - 1.0 ;
11826   if (y >= height)   y = height - 1.0 ;
11827   if (z >= depth)    z = depth - 1.0 ;
11828   if (x < 0.0)       x = 0.0 ;
11829   if (y < 0.0)       y = 0.0 ;
11830   if (z < 0.0)       z = 0.0 ;
11831 
11832   xm = MAX((int)x, 0) ;
11833   xp = MIN(width-1, xm+1) ;
11834   ym = MAX((int)y, 0) ;
11835   yp = MIN(height-1, ym+1) ;
11836   zm = MAX((int)z, 0) ;
11837   zp = MIN(depth-1, zm+1) ;
11838 
11839   xmd = x - (float)xm ;
11840   ymd = y - (float)ym ;
11841   xpd = (1.0f - xmd) ;
11842   ypd = (1.0f - ymd) ;
11843 
11844   switch (slice_direction)
11845     {
11846     case MRI_CORONAL:
11847       zp = nint(z) ;
11848       val11 = MRIgetVoxVal(mri, xm, ym, zp, 0) ;
11849       val12 = MRIgetVoxVal(mri, xm, yp, zp, 0) ;
11850       val21 = MRIgetVoxVal(mri, xp, ym, zp, 0) ;
11851       val22 = MRIgetVoxVal(mri, xp, yp, zp, 0) ;
11852       *pval = val = xpd * ypd * val11 + xpd * ymd * val12 + xmd * ypd * val21 +
11853         xmd * ymd * val22 ;
11854       break ;
11855     default:
11856       ErrorReturn
11857         (ERROR_UNSUPPORTED,
11858          (ERROR_UNSUPPORTED,
11859           "MRIsampleVolumeSlice: unsupported direction %d", slice_direction)) ;
11860       break ;
11861     }
11862   return(NO_ERROR) ;
11863 }
11864 
11865 float
11866 MRIvoxelsInLabelWithPartialVolumeEffects(MRI *mri, MRI *mri_vals, int label)
11867 {
11868   float   volume, vox_vol ;
11869   int     x, y, z, nbr_label_counts[MAX_CMA_LABELS];
11870   int     label_counts[MAX_CMA_LABELS], this_label, border;
11871   int     nbr_label, max_count, vox_label ;
11872   MRI     *mri_border ;
11873   float   label_means[MAX_CMA_LABELS], pv, mean_label, mean_nbr, val ;
11874 
11875   vox_vol = mri->xsize*mri->ysize*mri->zsize ;
11876 
11877   /* first find border voxels */
11878   mri_border = MRImarkLabelBorderVoxels(mri, NULL, label, 1, 1) ;
11879   if (DIAG_VERBOSE_ON && (Gdiag & DIAG_WRITE))
11880     MRIwrite(mri_border, "b.mgz") ;
11881   volume = 0 ;
11882   for (x = 0 ; x < mri->width ; x++)
11883     {
11884       for (y = 0 ; y < mri->height ; y++)
11885         {
11886           for (z = 0 ; z < mri->depth ; z++)
11887             {
11888               if (x == Gx && y == Gy && z == Gz)
11889                 DiagBreak() ;
11890               vox_label = MRIgetVoxVal(mri, x, y, z, 0) ;
11891               border = MRIgetVoxVal(mri_border, x, y, z, 0) ;
11892               if ((vox_label != label) && (border == 0))
11893                 continue ;
11894 
11895               if (border == 0)
11896                 volume += vox_vol ;
11897               else /* compute partial volume */
11898                 {
11899                   MRIcomputeLabelNbhd
11900                     (mri, mri_vals, x, y, z,
11901                      nbr_label_counts, label_means, 1, MAX_CMA_LABELS) ;
11902                   MRIcomputeLabelNbhd
11903                     (mri, mri_vals, x, y, z,
11904                      label_counts, label_means, 7, MAX_CMA_LABELS) ;
11905                   val =
11906                     MRIgetVoxVal(mri_vals, x, y, z, 0) ;  /* compute partial
11907                                                              volume based on
11908                                                              intensity */
11909                   mean_label = label_means[vox_label] ;
11910                   nbr_label = -1 ; max_count = 0 ;
11911                   /* look for a label that is a nbr and is
11912                      on the other side of val from the label mean */
11913                   for (this_label = 0 ;
11914                        this_label < MAX_CMA_LABELS ;
11915                        this_label++)
11916                     {
11917                       if (this_label == vox_label)
11918                         continue ;
11919                       if (nbr_label_counts[this_label] == 0)   /* not a nbr */
11920                         continue ;
11921 
11922                       if ((label_counts[this_label] > max_count) &&
11923                           ((label_means[this_label] - val) *
11924                            (mean_label - val) < 0))
11925                         {
11926                           max_count = label_means[this_label] ;
11927                           nbr_label = this_label ;
11928                         }
11929                     }
11930                   if (vox_label != label &&
11931                       nbr_label != label)  /* this struct not in voxel */
11932                     continue ;
11933 
11934                   if (max_count == 0)  /* couldn't find an appropriate label */
11935                     volume += vox_vol ;
11936                   else    /* compute partial volume pct */
11937                     {
11938                       mean_nbr = label_means[nbr_label] ;
11939                       pv = (val - mean_nbr) / (mean_label - mean_nbr) ;
11940                       if (vox_label == label)
11941                         volume += vox_vol * pv ;
11942                       else
11943                         volume += vox_vol * (1-pv) ;
11944                       if (pv < 0 || pv > 1)
11945                         DiagBreak() ;
11946                     }
11947                 }
11948             }
11949         }
11950     }
11951 
11952   MRIfree(&mri_border) ;
11953   return(volume) ;
11954 }
11955 
11956 MRI *
11957 MRImakeDensityMap(MRI *mri, MRI *mri_vals, int label, MRI *mri_dst)
11958 {
11959   float   vox_vol, volume ;
11960   int     x, y, z, nbr_label_counts[MAX_CMA_LABELS];
11961   int     label_counts[MAX_CMA_LABELS], this_label, border;
11962   int     nbr_label, max_count, vox_label ;
11963   MRI     *mri_border ;
11964   float   label_means[MAX_CMA_LABELS], pv, mean_label, mean_nbr, val ;
11965 
11966   if (mri_dst == NULL)
11967     mri_dst = MRIalloc(mri->width, mri->height, mri->depth, MRI_FLOAT) ;
11968 
11969   /* first find border voxels */
11970   mri_border = MRImarkLabelBorderVoxels(mri, NULL, label, 1, 1) ;
11971   if (DIAG_VERBOSE_ON && (Gdiag & DIAG_WRITE))
11972     MRIwrite(mri_border, "b.mgz") ;
11973   vox_vol = mri->xsize*mri->ysize*mri->zsize ;
11974   for (x = 0 ; x < mri->width ; x++)
11975     {
11976       for (y = 0 ; y < mri->height ; y++)
11977         {
11978           for (z = 0 ; z < mri->depth ; z++)
11979             {
11980               if (x == Gx && y == Gy && z == Gz)
11981                 DiagBreak() ;
11982               vox_label = MRIgetVoxVal(mri, x, y, z, 0) ;
11983               border = MRIgetVoxVal(mri_border, x, y, z, 0) ;
11984               if ((vox_label != label) && (border == 0))
11985                 continue ;
11986 
11987               volume = vox_vol ;
11988               if (border == 0)
11989                 volume = vox_vol ;
11990               else  /* compute partial volume */
11991                 {
11992                   MRIcomputeLabelNbhd
11993                     (mri, mri_vals, x, y, z,
11994                      nbr_label_counts, label_means, 1, MAX_CMA_LABELS) ;
11995                   MRIcomputeLabelNbhd
11996                     (mri, mri_vals, x, y, z,
11997                      label_counts, label_means, 7, MAX_CMA_LABELS) ;
11998                   val = 
11999                     MRIgetVoxVal(mri_vals, x, y, z, 0) ;  /* compute partial
12000                                                              volume based on
12001                                                              intensity */
12002                   mean_label = label_means[vox_label] ;
12003                   nbr_label = -1 ; max_count = 0 ;
12004                   /* look for a label that is a nbr and is
12005                      on the other side of val from the label mean */
12006                   for (this_label = 0 ;
12007                        this_label < MAX_CMA_LABELS ;
12008                        this_label++)
12009                     {
12010                       if (this_label == vox_label)
12011                         continue ;
12012                       if (nbr_label_counts[this_label] == 0)   /* not a nbr */
12013                         continue ;
12014 
12015                       if ((label_counts[this_label] > max_count) &&
12016                           ((label_means[this_label] - val) *
12017                            (mean_label - val) < 0))
12018                         {
12019                           max_count = label_means[this_label] ;
12020                           nbr_label = this_label ;
12021                         }
12022                     }
12023                   if (vox_label != label &&
12024                       nbr_label != label)  /* this struct not in voxel */
12025                     continue ;
12026 
12027                   if (max_count > 0)  /* compute partial volume pct */
12028                     {
12029                       mean_nbr = label_means[nbr_label] ;
12030                       pv = (val - mean_nbr) / (mean_label - mean_nbr) ;
12031                       if (vox_label == label)
12032                         volume = pv*vox_vol ;
12033                       else
12034                         volume = vox_vol * (1-pv) ;
12035                       if (pv < 0 || pv > 1)
12036                         DiagBreak() ;
12037                     }
12038                 }
12039               MRIsetVoxVal(mri_dst, x, y, z, 0, volume) ;
12040             }
12041         }
12042     }
12043 
12044   MRIfree(&mri_border) ;
12045   return(mri_dst) ;
12046 }
12047 
12048 MRI *
12049 MRImarkLabelBorderVoxels
12050 (MRI *mri_src, MRI *mri_dst, int label, int mark, int six_connected)
12051 {
12052   int  x, y, z, xk, yk, zk, xi, yi, zi, this_label, that_label, border ;
12053 
12054   if (mri_dst == NULL)
12055     mri_dst = MRIclone(mri_src, NULL) ;
12056 
12057   for (x = 0 ; x < mri_src->width ; x++)
12058     {
12059       for (y = 0 ; y < mri_src->height ; y++)
12060         {
12061           for (z = 0 ; z < mri_src->depth ; z++)
12062             {
12063               this_label = MRIgetVoxVal(mri_src, x, y, z, 0) ;
12064               border = 0 ;
12065               for (xk = -1 ; xk <= 1 && !border ; xk++)
12066                 {
12067                   xi = mri_src->xi[x+xk] ;
12068                   for (yk = -1 ; yk <= 1 && !border ; yk++)
12069                     {
12070                       yi = mri_src->yi[y+yk] ;
12071                       for (zk = -1 ; zk <= 1 ; zk++)
12072                         {
12073                           if (six_connected && (abs(xk)+abs(yk)+abs(zk) != 1))
12074                             continue ;
12075                           zi = mri_src->zi[z+zk] ;
12076                           that_label = MRIgetVoxVal(mri_src, xi, yi, zi, 0) ;
12077                           if (((this_label == label) &&
12078                                (that_label != label)) ||
12079                               ((this_label != label) &&
12080                                (that_label == label)))
12081                             {
12082                               border = 1 ;
12083                               break ;
12084                             }
12085                         }
12086                     }
12087                 }
12088               if (border)
12089                 MRIsetVoxVal(mri_dst, x, y, z, 0, mark) ;
12090             }
12091         }
12092     }
12093 
12094   return(mri_dst) ;
12095 }
12096 
12097 int
12098 MRIcomputeLabelNbhd
12099 (MRI *mri_labels, MRI *mri_vals,
12100  int x, int y, int z, int *label_counts, float *label_means,
12101  int whalf, int max_labels)
12102 {
12103   int    xi, yi, zi, xk, yk, zk, label ;
12104   float  val ;
12105 
12106   memset(label_counts, 0, sizeof(label_counts[0])*max_labels) ;
12107   memset(label_means, 0, sizeof(label_means[0])*max_labels) ;
12108   for (xk = -whalf ; xk <= whalf ; xk++)
12109     {
12110       xi = mri_vals->xi[x+xk] ;
12111       for (yk = -whalf ; yk <= whalf ; yk++)
12112         {
12113           yi = mri_vals->yi[y+yk] ;
12114           for (zk = -whalf ; zk <= whalf ; zk++)
12115             {
12116               zi = mri_vals->zi[z+zk] ;
12117               label = MRIgetVoxVal(mri_labels, xi, yi, zi, 0) ;
12118               val = MRIgetVoxVal(mri_vals, xi, yi, zi, 0) ;
12119               label_counts[label]++ ;
12120               label_means[label] += val ;
12121             }
12122         }
12123     }
12124 
12125   for (label = 0 ; label < max_labels ; label++)
12126     if (label_counts[label] > 0)
12127       label_means[label] /= label_counts[label] ;
12128   return(NO_ERROR) ;
12129 }
12130 
12131 /**
12132  * void MRIcalCRASforSampledVolume
12133  *
12134  * @param src MRI* volume
12135  * @param dst MRI* sampled volume
12136  * @param pr  output ptr to c_r
12137  * @param pa  output ptr to c_a
12138  * @param ps  output ptr to c_s
12139  */
12140 void MRIcalcCRASforSampledVolume
12141 (MRI *src, MRI *dst, Real *pr, Real *pa, Real *ps)
12142 {
12143   // get the voxel position of the "center" voxel of the dst in the src volume
12144   // i.e. sample is 2, then get the voxel position 64 in the src volume
12145   //      thus  it is 128.5 (in the src) for 64 (in the dst)
12146   Real sx, sy, sz;
12147   int dx, dy, dz;
12148   int samplex, sampley, samplez;
12149 
12150   // error check first
12151   if ((src->width)%(dst->width) != 0)
12152     ErrorExit
12153       (ERROR_BADPARM, "src width must be integer multiple of dst width");
12154   if ((src->height)%(dst->height) != 0)
12155     ErrorExit
12156       (ERROR_BADPARM, "src height must be integer multiple of dst height");
12157   if ((src->depth)%(dst->depth) != 0)
12158     ErrorExit
12159       (ERROR_BADPARM, "src depth must be integer multiple of dst depth");
12160 
12161   samplex = src->width/dst->width;
12162   sampley = src->height/dst->height;
12163   samplez = src->depth/dst->depth;
12164 
12165   // "center" voxel position in dst
12166   dx = dst->width/2; // if the length is odd,
12167                      // then it does the right thing (truncation)
12168   dy = dst->height/2;// i.e.  0 1 2 then 3/2 = 1,  0 1 2 3 then 4/2=2
12169   dz = dst->depth/2;
12170   // corresponding position in src
12171   sx = dx*samplex + (samplex-1.)/2.; // ((dx*samplex - 0.5) +
12172                                      // ((dx+1)*samplex -0.5))/2.
12173   sy = dy*sampley + (sampley-1.)/2.;
12174   sz = dz*samplez + (samplez-1.)/2.;
12175   //
12176   // Example
12177   // | 0 1 2 | 3 4 5 | 6 7 8 | -(sample by 3).
12178   // |   0   |   1   |   2   |
12179   //                                       1 (3/2) in dst corresponds
12180   //                                       to 1*3+(3-1)/2 = 4! in src
12181   //
12182   // | 0 1 2 3 | 4 5 6 7 |     -(sample by 4)->0 1
12183   // |    0    |    1    |                        1 (2/2) in dst corresponds
12184   //                                              to 1*4+(4-1)/2 = 5.5 in src
12185 
12186   // get ras of the "center" voxel position in dst
12187   if (!src->i_to_r__)
12188     {
12189       src->i_to_r__ = extract_i_to_r(src);
12190       src->r_to_i__ = extract_r_to_i(src);
12191     }
12192   TransformWithMatrix(src->i_to_r__, sx, sy, sz, pr, pa, ps);
12193 
12194   if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
12195     fprintf(stderr, "c_ras for sample volume is (%f, %f, %f) "
12196             "compared with the src (%f, %f, %f)\n",
12197             *pr, *pa, *ps, src->c_r, src->c_a, src->c_s);
12198 }
12199 
12200 /**
12201  * MRIcalcCRASfroExtractedVolume
12202  *
12203  * @param src  MRI* src volume
12204  * @param x0   src start position of the extraction region
12205  * @param y0
12206  * @param z0
12207  * @param x1   target start position of the extracted region
12208  * @param y1
12209  * @param z1
12210  * @param pr   output Real*  c_r
12211  * @param pa                 c_a
12212  * @param ps                 c_s
12213  */
12214 void MRIcalcCRASforExtractedVolume
12215 (MRI *src, MRI *dst, int x0, int y0, int z0, int x1, int y1, int z1,
12216  Real *pr, Real *pa, Real *ps)
12217 {
12218   Real cx, cy, cz;
12219   // The "center" voxel position of the
12220   // extracted volume in the original voxel position
12221   //        x1 of dst corresponds to x0 of src
12222   // Thus, the "center" of dst corresponds to that of the src is
12223   cx = x0+(Real)dst->width/2 - x1;  // integer divide cutoff extra
12224   cy = y0+(Real)dst->height/2 - y1;
12225   cz = z0+(Real)dst->depth/2 - z1;
12226 
12227   if (!src->i_to_r__)
12228     {
12229       src->i_to_r__ = extract_i_to_r(src);
12230       src->r_to_i__ = extract_r_to_i(src);
12231     }
12232   TransformWithMatrix(src->i_to_r__, cx, cy, cz, pr, pa, ps);
12233   // got where the RAS position of the new volume position
12234   // we have to translate so that we can get the same value
12235   // under the new volume
12236 
12237   if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
12238     fprintf(stderr, "c_ras for sample volume is (%f, %f, %f) "
12239             "compared with the src (%f, %f, %f)\n",
12240             *pr, *pa, *ps, src->c_r, src->c_a, src->c_s);
12241 }
12242 
12243 // transform is the hires to lowres vox-to-vox transform
12244 void MRIcalcCRASforHiresVolume
12245 (MRI *hires, MRI *lowres, MATRIX *vox_xform, Real *pr, Real *pa, Real *ps)
12246 {
12247   // get where the center of hires volume goes to in the lowres volume
12248   Real cx, cy, cz;
12249   Real dx, dy, dz;
12250   cx = hires->width/2; cy = hires->height/2; cz = hires->depth/2;
12251   TransformWithMatrix(vox_xform, cx, cy, cz, &dx, &dy, &dz);
12252   // get the c_ras values for this position
12253   TransformWithMatrix(lowres->i_to_r__, dx, dy, dz, pr, pa, ps);
12254   // if we use this c_ras value for the transformed hires volume, then
12255   // the volume will be containing the original points
12256 }
12257 
12258 // transform is src to dst vox to vox transform
12259 // return rotated src whose center is at the right place
12260 // Just rotating the original volume make the non-zero voxels go
12261 // outside of the rotated volume.  This routine will keep the
12262 // center of the rotated volume at the right location.
12263 MRI *
12264 MRIsrcTransformedCentered
12265 (MRI *src, MRI *dst, MATRIX *stod_voxtovox, int interp_method)
12266 {
12267   Real cr, ca, cs;
12268   MRI *rotated;
12269   MATRIX *stosrotVox;
12270   MATRIX *tmp;
12271 
12272   // get the c_ras value for the rotated volume
12273   MRIcalcCRASforHiresVolume(src, dst, stod_voxtovox, &cr, &ca, &cs);
12274   rotated = MRIclone(src, NULL);
12275   // reset the rotated volume
12276   rotated->c_r = cr;
12277   rotated->c_a = ca;
12278   rotated->c_s = cs;
12279   MRIreInitCache(rotated); // recalculate the transform
12280   // the map is the following
12281   //
12282   //     src -->    RAS
12283   //       |         |
12284   //       |given    |
12285   //       V         V
12286   //     dst -->    RAS
12287   //       |         |
12288   //       |       (identity)
12289   //       V         |
12290   //     src'  -->  RAS
12291   // new rotated src volume whose center is at the right location
12292   //
12293   tmp = MatrixMultiply(rotated->r_to_i__, dst->i_to_r__, NULL);
12294   stosrotVox = MatrixMultiply(tmp, stod_voxtovox, NULL);
12295   MRIlinearTransformInterp(src, rotated, stosrotVox, interp_method);
12296   return rotated;
12297 }
12298 
12299 ////////////////////////////////////////////////////////////////////////////
12300 // No sample method ////////////////////////////////////////////////////////
12301 // using the src and orig_dst to modify
12302 // the direction cosines and c_(ras) value
12303 // so that it will be rotated in the RAS space but no pixel is sampled
12304 MRI *MRITransformedCenteredMatrix(MRI *src, MRI *orig_dst, MATRIX *m_L)
12305 {
12306   LTA *lta ;
12307   MRI *mri_dst ;
12308 
12309   lta = LTAalloc(1, NULL) ;
12310   MatrixCopy(m_L, lta->xforms[0].m_L) ;
12311   lta->type = LINEAR_VOX_TO_VOX ;
12312   mri_dst = MRITransformedCentered(src, orig_dst, lta) ;
12313   LTAfree(&lta) ;
12314   return(mri_dst) ;
12315 }
12316 MRI *MRITransformedCentered(MRI *src, MRI *orig_dst, LTA *lta)
12317 {
12318   MRI *dst = 0;
12319   Real cx, cy, cz;
12320   Real cr, ca, cs;
12321   MATRIX *dstToRas = 0;
12322   MATRIX *SI = 0;
12323   MATRIX *D = 0;
12324   LT *tran = &lta->xforms[0];
12325 
12326   dst = MRIcopy(src, NULL);
12327 
12328   if (lta->num_xforms > 1)
12329     ErrorExit(ERROR_BADPARM, "The LTA contains more than one transforms.");
12330 
12331   // first verify the consistency of the transform stored geometry vs. argument
12332   if (tran->dst.valid == 1)
12333     {
12334       // compare the one with orig_dst to the stored one
12335       VG dstvg, storedvg;
12336       getVolGeom(orig_dst, &dstvg);
12337       storedvg.valid = tran->dst.valid;
12338       storedvg.width = tran->dst.width;
12339       storedvg.height = tran->dst.height;
12340       storedvg.depth = tran->dst.depth;
12341       storedvg.xsize = tran->dst.xsize;
12342       storedvg.ysize = tran->dst.ysize;
12343       storedvg.zsize = tran->dst.zsize;
12344       storedvg.x_r = tran->dst.x_r;
12345       storedvg.x_a = tran->dst.x_a;
12346       storedvg.x_s = tran->dst.x_s;
12347       storedvg.y_r = tran->dst.y_r;
12348       storedvg.y_a = tran->dst.y_a;
12349       storedvg.y_s = tran->dst.y_s;
12350       storedvg.z_r = tran->dst.z_r;
12351       storedvg.z_a = tran->dst.z_a;
12352       storedvg.z_s = tran->dst.z_s;
12353       storedvg.c_r = tran->dst.c_r;
12354       storedvg.c_a = tran->dst.c_a;
12355       storedvg.c_s = tran->dst.c_s;
12356       if (!vg_isEqual(&dstvg, &storedvg))
12357         {
12358           fprintf
12359             (stderr,
12360              "WARNING: stored destination volume for the "
12361              "transform differes from the argument.");
12362         }
12363     }
12364   if (tran->src.valid == 1)
12365     {
12366       // compare the one with orig_dst to the stored one
12367       VG srcvg, storedvg;
12368       getVolGeom(src, &srcvg);
12369       storedvg.valid = tran->src.valid;
12370       storedvg.width = tran->src.width;
12371       storedvg.height = tran->src.height;
12372       storedvg.depth = tran->src.depth;
12373       storedvg.xsize = tran->src.xsize;
12374       storedvg.ysize = tran->src.ysize;
12375       storedvg.zsize = tran->src.zsize;
12376       storedvg.x_r = tran->src.x_r;
12377       storedvg.x_a = tran->src.x_a;
12378       storedvg.x_s = tran->src.x_s;
12379       storedvg.y_r = tran->src.y_r;
12380       storedvg.y_a = tran->src.y_a;
12381       storedvg.y_s = tran->src.y_s;
12382       storedvg.z_r = tran->src.z_r;
12383       storedvg.z_a = tran->src.z_a;
12384       storedvg.z_s = tran->src.z_s;
12385       storedvg.c_r = tran->src.c_r;
12386       storedvg.c_a = tran->src.c_a;
12387       storedvg.c_s = tran->src.c_s;
12388       if (!vg_isEqual(&srcvg, &storedvg))
12389         {
12390           fprintf(stderr, "WARNING: stored destination volume for the "
12391                   "transform differes from the argument.");
12392         }
12393     }
12394 
12395   if (lta->type == LINEAR_RAS_TO_RAS)
12396     {
12397       MATRIX *tmp;
12398       //
12399       //      src   -->   RAS
12400       //       |           |
12401       //       | M         | Y
12402       //       V           V
12403       //    orig_dst -->  RAS
12404       //
12405       // transform it to the vox-to-vox
12406       // now calculate M
12407       tmp = MatrixMultiply(tran->m_L, src->i_to_r__, NULL);
12408       MatrixFree(&tran->m_L);
12409       tran->m_L = MatrixMultiply(orig_dst->r_to_i__, tmp, NULL);
12410       MatrixFree(&tmp);
12411       lta->type = LINEAR_VOX_TO_VOX;
12412     }
12413 
12414   if (lta->type != LINEAR_VOX_TO_VOX)
12415     ErrorExit
12416       (ERROR_BADPARM,
12417        "The LTA does not contain LINEASR_RAS_TO_RAS nor LINEAR_VOX_TO_VOX.");
12418   //
12419   //      src   -->   RAS
12420   //       |           |
12421   //       | M         | Y
12422   //       V           V
12423   //    orig_dst -->  RAS
12424   //       |           |
12425   //       |       (identity)
12426   //       V           |
12427   //      dst   -->   RAS
12428   // new rotated src volume whose center is at the right location
12429   //            ?
12430   // we try src->dst is identity (no sampling)
12431   //
12432   //    Y = i_to_r(orig_dst) * M * r_to_i(src)
12433   //
12434   // Thus we have simpler picture
12435   //
12436   //      src   -----> RAS
12437   //       |            |
12438   //    (identity)     (Y)
12439   //       |            |
12440   //       V            V
12441   //      dst   -----> RAS
12442   //            (???)
12443   //
12444   // Thus
12445   //      (???) = Y * i_to_r(src)
12446   //            = i_to_r(orig_dst) * M * r_to_i(src) * i_to_r(src)
12447   //
12448   //      (???) = i_to_r(orig_dst) * M           (A)
12449   //
12450   // Thus we derive direction cosines and c_(ras) from ???
12451   //
12452   //      (???)  =  ( X   T ) ( S  0 )    where S is the voxel size
12453   //                ( 0   1 ) ( 0  1 )
12454   // or
12455   //      ( X  T ) = (???) * (S^(-1) 0 )         (B)
12456   //      ( 0  1 )           ( 0     1 )
12457   //
12458   //
12459   dstToRas = MatrixMultiply(orig_dst->i_to_r__, tran->m_L, NULL);
12460 
12461   SI = MatrixAlloc(4, 4, MATRIX_REAL);
12462   *MATRIX_RELT(SI, 1, 1) = 1./dst->xsize ;
12463   *MATRIX_RELT(SI, 2, 2) = 1./dst->ysize ;
12464   *MATRIX_RELT(SI, 3, 3) = 1./dst->zsize ;
12465   *MATRIX_RELT(SI, 4, 4) = 1. ;
12466 
12467   D = MatrixMultiply(dstToRas, SI, NULL);
12468 
12469   dst->x_r = *MATRIX_RELT(D, 1, 1);
12470   dst->x_a = *MATRIX_RELT(D, 2, 1);
12471   dst->x_s = *MATRIX_RELT(D, 3, 1);
12472   dst->y_r = *MATRIX_RELT(D, 1, 2);
12473   dst->y_a = *MATRIX_RELT(D, 2, 2);
12474   dst->y_s = *MATRIX_RELT(D, 3, 2);
12475   dst->z_r = *MATRIX_RELT(D, 1, 3);
12476   dst->z_a = *MATRIX_RELT(D, 2, 3);
12477   dst->z_s = *MATRIX_RELT(D, 3, 3);
12478 
12479   MatrixFree(&D);
12480   MatrixFree(&SI);
12481 
12482   // c_ras is calculated by
12483   //
12484   //      ( X  T )(S 0)(dstwidth/2 )  = (c_r)
12485   // or  i_to_r(orig_dst) * M * (dstwidth/2 ) = C'
12486   //      ( 0  1 )(0 1)(dstheight/2)    (c_a)
12487   //                               (dstheight/2)
12488   //                   (dstdepth/2 )    (c_s)
12489   //                                                  (dstdepth/2 )
12490   //                   (    1      )    ( 1 )               (    1      )
12491   //
12492   // This is the same as the original center point
12493   // is mapped to orig_dst and then obtaining
12494   // its ras position! (because src and dst has the
12495   // same volume size).  The only difference
12496   // is its orientation with respect to orig_dst RAS.  Good
12497   //
12498   // get where the center of hires volume goes to in the lowres volume
12499   cx = dst->width/2; cy = dst->height/2; cz = dst->depth/2;
12500   // get the c_ras values for this position
12501   TransformWithMatrix(dstToRas, cx, cy, cz, &cr, &ca, &cs);
12502   // if we use this c_ras value for the transformed hires volume, then
12503   // the volume will be containing the original points
12504   dst->c_r = cr;
12505   dst->c_a = ca;
12506   dst->c_s = cs;
12507 
12508   // when you change the direction cosine, you have to do this
12509   MRIreInitCache(dst);
12510 
12511   MatrixFree(&dstToRas);
12512 
12513   return dst;
12514 }
12515 int
12516 MRIcropBoundingBox(MRI *mri,    MRI_REGION  *box)
12517 {
12518   box->x = MAX(0, box->x) ; box->y = MAX(0, box->y) ;box->z = MAX(0, box->z) ;
12519   box->dx = MIN(mri->width-box->x-1, box->dx) ;
12520   box->dy = MIN(mri->height-box->y-1, box->dy) ;
12521   box->dz = MIN(mri->depth-box->z-1, box->dz) ;
12522   return(NO_ERROR) ;
12523 }
12524 
12525 MATRIX *
12526 MRIgetVoxelToVoxelXform(MRI *mri_src, MRI *mri_dst)
12527 {
12528   MATRIX *m_ras2vox_dst, *m_vox2ras_src, *m_vox2vox ;
12529 
12530   m_vox2ras_src = MRIgetVoxelToRasXform(mri_src) ;
12531   m_ras2vox_dst = MRIgetRasToVoxelXform(mri_dst) ;
12532   m_vox2vox = MatrixMultiply(m_ras2vox_dst, m_vox2ras_src, NULL) ;
12533   MatrixFree(&m_vox2ras_src) ; MatrixFree(&m_ras2vox_dst) ;
12534   return(m_vox2vox) ;
12535 }
12536 
12537 /*--------------------------------------------------------------
12538   MRIfovCol(mri) - computes the edge-to-edge FOV in the column
12539   direction. fov is in mm.
12540   -------------------------------------------------------------*/
12541 float MRIfovCol(MRI *mri)
12542 {
12543   MATRIX *M,*v,*a,*b,*d;
12544   float fov;
12545 
12546   M = MRIgetVoxelToRasXform(mri) ;
12547   v = MatrixAlloc(4,1,MATRIX_REAL);
12548   v->rptr[1][4] = 1;
12549   v->rptr[1][1] = mri->width-1+0.5; // edge of last column
12550   a = MatrixMultiply(M,v,NULL);     // xyz of last column
12551   v->rptr[1][1] = -0.5;             // edge of first column
12552   b = MatrixMultiply(M,v,NULL);     // xyz of first column
12553   d = MatrixSubtract(a,b,NULL); // xyz difference
12554   fov = VectorLen(d);           // fov is in mm
12555   MatrixFree(&M);
12556   MatrixFree(&v);
12557   MatrixFree(&a);
12558   MatrixFree(&b);
12559   MatrixFree(&d);
12560 
12561   //printf("MRIfovCol() %g\n",fov);
12562   return(fov);
12563 }
12564 /* ---------------------------------------------------------------------
12565    MRIorientationStringToDircos() - sets the direction cosines of to
12566    be that dictated by the Orientation String. This is helpful for
12567    setting the direction cosines when the information is not present
12568    in a header (eg, with FSL analyze format).  The Orientation String
12569    is a three character string indicating the primary direction of
12570    each axis in the 3d matrix. The characters can be L,R,A,P,I,S.  The
12571    string must be valid (see MRIcheckOrientationString). If the string
12572    is not valid, the errors are printed and a 1 is returned. Eg, of
12573    valid strings are RAS, LPS, LAI. Invalid are ABC (B and C are not
12574    valid), RAP (the AP axis is represented twice, IS axis not at all).
12575    There are 48 possible valid strings. This should only be used to
12576    get the direction cosines "about right".
12577    --------------------------------------------------------------------*/
12578 
12579 int MRIorientationStringToDircos(MRI *mri, char *ostr)
12580 {
12581   int c,r=0;
12582   double Mdc[3][3], v=0;
12583   char *errstr;
12584 
12585   errstr = MRIcheckOrientationString(ostr);
12586   if(errstr != NULL){
12587     printf("ERROR: in orientation string %s\n",ostr);
12588     printf("%s",errstr);
12589     free(errstr);
12590     return(1);
12591   }
12592 
12593   // Initialize the matrix of direction cosines (Mdc)
12594   for(c=0; c<3; c++) for(r=0; r<3; r++) Mdc[r][c] = 0;
12595 
12596   // Each column of Mdc corresponds to a different axis which corresonds to
12597   // a different letter in the orientation string. The value of the letter
12598   // determine which row of the Mdc will be affected.
12599   for(c=0; c<3; c++){
12600     switch(toupper(ostr[c])){
12601     case 'L': r=0; v=-1; break;
12602     case 'R': r=0; v=+1; break;
12603     case 'P': r=1; v=-1; break;
12604     case 'A': r=1; v=+1; break;
12605     case 'I': r=2; v=-1; break;
12606     case 'S': r=2; v=+1; break;
12607     }
12608     Mdc[r][c] = v;
12609   }
12610   mri->x_r = Mdc[0][0];
12611   mri->x_a = Mdc[1][0];
12612   mri->x_s = Mdc[2][0];
12613 
12614   mri->y_r = Mdc[0][1];
12615   mri->y_a = Mdc[1][1];
12616   mri->y_s = Mdc[2][1];
12617 
12618   mri->z_r = Mdc[0][2];
12619   mri->z_a = Mdc[1][2];
12620   mri->z_s = Mdc[2][2];
12621 
12622   return(0);
12623 }
12624 /* ---------------------------------------------------------------
12625    MRIcheckOrientationString() - this checks the orientation string
12626    to make sure that it is valid. "Valid" means that all axes are
12627    represented exactly once and no invalid characters are present
12628    in the string. Case-insensitive. Returns NULL if everything is
12629    ok, otherwise is returns a string that lists all the errors
12630    it encountered.
12631    ---------------------------------------------------------------*/
12632 char *MRIcheckOrientationString(char *ostr)
12633 {
12634   int c, nsag=0, ncor=0, nax=0, err;
12635   char errstr[1000], *errstrret=NULL;
12636 
12637   errstr[0] = '\0';
12638   err = 0;
12639 
12640   for(c=0; c<3; c++){
12641     switch(toupper(ostr[c])){
12642     case 'L': nsag++; break;
12643     case 'R': nsag++; break;
12644     case 'P': ncor++; break;
12645     case 'A': ncor++; break;
12646     case 'I': nax++;  break;
12647     case 'S': nax++;  break;
12648     default:
12649       sprintf(errstr,"%s  Character %c in position %d is invalid.\n",
12650               errstr,ostr[c],c+1);
12651       err = 1;
12652       break;
12653     }
12654   }
12655 
12656   if(nsag > 1){
12657     sprintf(errstr,"%s  LR axis represented multiple times.\n",errstr);
12658     err = 1;
12659   }
12660   if(ncor > 1){
12661     sprintf(errstr,"%s  PA axis represented multiple times.\n",errstr);
12662     err = 1;
12663   }
12664   if(nax > 1){
12665     sprintf(errstr,"%s  IS axis represented multiple times.\n",errstr);
12666     err = 1;
12667   }
12668   if(nsag == 0){
12669     sprintf(errstr,"%s  LR axis not represented.\n",errstr);
12670     err = 1;
12671   }
12672   if(ncor == 0){
12673     sprintf(errstr,"%s  PA axis not represented.\n",errstr);
12674     err = 1;
12675   }
12676   if(nax == 0){
12677     sprintf(errstr,"%s  IS axis not represented.\n",errstr);
12678     err = 1;
12679   }
12680 
12681   if(err){
12682     errstrret = (char *) calloc(sizeof(char),strlen(errstr)+1);
12683     memcpy(errstrret,errstr,strlen(errstr));
12684   }
12685 
12686   return(errstrret);
12687 }
12688 /*------------------------------------------------------------------
12689   MRIdircosToOrientationString() - examines the direction cosines and
12690   creates an Orientation String. The Orientation String is a three
12691   character string indicating the primary direction of each axis
12692   in the 3d matrix. The characters can be L,R,A,P,I,S. Case is not
12693   important, but upper case is used here. If ras_good_flag == 0,
12694   then ostr = ??? and 1 is returned.
12695   ------------------------------------------------------------------*/
12696 int MRIdircosToOrientationString(MRI *mri, char *ostr)
12697 {
12698   int c;
12699   float Mdc[3][3], sag, cor, ax;
12700 
12701   if(! mri->ras_good_flag){
12702     ostr[0] = '?';
12703     ostr[1] = '?';
12704     ostr[2] = '?';
12705     return(1);
12706   }
12707 
12708   Mdc[0][0] = mri->x_r;
12709   Mdc[1][0] = mri->x_a;
12710   Mdc[2][0] = mri->x_s;
12711 
12712   Mdc[0][1] = mri->y_r;
12713   Mdc[1][1] = mri->y_a;
12714   Mdc[2][1] = mri->y_s;
12715 
12716   Mdc[0][2] = mri->z_r;
12717   Mdc[1][2] = mri->z_a;
12718   Mdc[2][2] = mri->z_s;
12719 
12720   for(c=0; c<3; c++) ostr[c] = '\0';
12721 
12722   for(c=0; c<3; c++){
12723     sag = Mdc[0][c]; // LR axis
12724     cor = Mdc[1][c]; // PA axis
12725     ax  = Mdc[2][c]; // IS axis
12726     //printf("c = %d, sag = %g, cor = %g, ax = %g\n",c,sag,cor,ax);
12727     if(fabs(sag) > fabs(cor) && fabs(sag) > fabs(ax)){
12728       if(sag > 0) ostr[c] = 'R';
12729       else        ostr[c] = 'L';
12730       continue;
12731     }
12732     if(fabs(cor) > fabs(ax)){
12733       if(cor > 0) ostr[c] = 'A';
12734       else        ostr[c] = 'P';
12735       continue;
12736     }
12737     if(ax > 0) ostr[c] = 'S';
12738     else       ostr[c] = 'I';
12739   }
12740   return(0);
12741 
12742 }
12743 /*-------------------------------------------------------------------
12744   MRIsliceDirectionName() - returns the name of the primary slice
12745   orientation base on the direction cosine. If mri->ras_good_flag=0,
12746   then "unknown" is returned.
12747   -------------------------------------------------------------------*/
12748 char *MRIsliceDirectionName(MRI *mri)
12749 {
12750   char ostr[4];
12751   char *slicedir = NULL;
12752   char *rtstr;
12753   int len;
12754 
12755   ostr[3] = '\0';
12756 
12757   MRIdircosToOrientationString(mri, ostr);
12758   if(toupper(ostr[2]) == 'L'|| toupper(ostr[2]) == 'R')
12759     slicedir = "sagittal";
12760   if(toupper(ostr[2]) == 'P'|| toupper(ostr[2]) == 'A')
12761     slicedir = "coronal";
12762   if(toupper(ostr[2]) == 'I'|| toupper(ostr[2]) == 'S')
12763     slicedir = "axial";
12764   if(! mri->ras_good_flag) slicedir = "unknown";
12765 
12766   len = strlen(slicedir);
12767   rtstr = (char *) calloc(sizeof(char),len+1);
12768   memcpy(rtstr,slicedir,len);
12769 
12770   return(rtstr);
12771 }
12772 MRI *
12773 MRIdistanceTransform
12774 (MRI *mri_src, MRI *mri_dist, int label, float max_dist, int mode)
12775 {
12776   int x, y, z, width, height, depth, xi, yi, zi;
12777   int xk, yk, zk, changed, found, i ;
12778   MRI *mri_processed ;
12779   float dist, min_dist ;
12780   VOXEL_LIST  *vl_current, *vl_new ;
12781 
12782   width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth ;
12783   if (max_dist < 0)
12784     max_dist = 2*MAX(MAX(width,height),depth);
12785   if (mri_dist == NULL)
12786     {
12787       mri_dist = MRIalloc(width, height, depth, MRI_FLOAT) ;
12788       MRIcopyHeader(mri_src, mri_dist) ;
12789     }
12790   else
12791     MRIclear(mri_dist) ;
12792 
12793   if (mode != DTRANS_MODE_OUTSIDE)
12794     vl_current = VLSTcreate(mri_src, label, label, NULL, 0, 1) ;
12795   else
12796     vl_current = VLSTcreate(mri_src, label, label, NULL, 0, 0) ;
12797   vl_new = VLSTdilate(vl_current, VL_DILATE_REPLACE, NULL) ;
12798 
12799   mri_processed = VLSTcreateMri(vl_current, 128) ;
12800   if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
12801     MRIwrite(mri_processed, "p.mgz") ;
12802 
12803   do
12804     {
12805       for (i = 0 ; i < vl_new->nvox ; i++)
12806         {
12807           x = vl_new->xi[i] ;
12808           y = vl_new->yi[i] ;
12809           z = vl_new->zi[i] ;
12810           found = 0 ; min_dist = 1e8 ;
12811           for (xk = -1 ; xk <= 1 ; xk++)  // find min dist of nbrs
12812             {
12813               xi = mri_src->xi[x+xk] ;
12814               for (yk = -1 ; yk <= 1 ; yk++)
12815                 {
12816                   yi = mri_src->yi[y+yk] ;
12817                   for (zk = -1 ; zk <= 1 ; zk++)
12818                     {
12819                       zi = mri_src->zi[z+zk] ;
12820                       if (MRIvox(mri_processed, xi, yi, zi) == 0)
12821                         continue ;
12822                       dist = MRIgetVoxVal(mri_dist, xi, yi, zi, 0) ;
12823                       dist += sqrt(xk*xk+yk*yk+zk*zk) ;
12824                       if (found == 0 || dist < min_dist)
12825                         {
12826                           found = 1 ;
12827                           min_dist = dist ;
12828                         }
12829                     }
12830                 }
12831             }
12832 
12833           if (found > 0)
12834             {
12835               changed++ ;
12836               MRIsetVoxVal(mri_dist, x, y, z, 0, min_dist) ;
12837             }
12838           else
12839             DiagBreak() ;
12840         }
12841 
12842       VLSTfree(&vl_current) ;
12843       VLSTaddToMri(vl_new, mri_processed, 128) ;
12844       vl_current = vl_new ;
12845       vl_new = VLSTdilate(vl_current, VL_DILATE_REPLACE, mri_processed) ;
12846 #if 0
12847       if (vl_new == NULL)
12848         printf("complete\n") ;
12849       else
12850         printf("examining %d voxels...\n", vl_new->nvox) ;
12851 #endif
12852     } while (vl_new != NULL) ;
12853 
12854   if (mode != DTRANS_MODE_OUTSIDE)  // set interior distances to negative vals
12855     {
12856       int x, y, z ;
12857 
12858       for (x = 0 ; x < mri_src->width ; x++)
12859         {
12860           for (y = 0 ; y < mri_src->height ; y++)
12861             {
12862               for (z = 0 ; z < mri_src->depth ; z++)
12863                 {
12864                   if (x == Gx && y == Gy && z == Gz)
12865                     DiagBreak() ;
12866                   if (FEQUAL(MRIgetVoxVal(mri_src, x, y, z, 0), label))
12867                     {
12868                       dist = MRIgetVoxVal(mri_dist, x, y, z, 0) ;
12869                       if (!FZERO(dist))
12870                         MRIsetVoxVal(mri_dist, x, y, z, 0, -dist) ;
12871                     }
12872                 }
12873             }
12874         }
12875     }
12876 
12877   if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
12878     MRIwrite(mri_dist, "dist.mgz") ;
12879   VLSTfree(&vl_current)  ;
12880   MRIfree(&mri_processed) ;
12881 
12882   if (mode == DTRANS_MODE_UNSIGNED)
12883     MRIabs(mri_dist, mri_dist) ;
12884   return(mri_dist) ;
12885 }
12886 
12887 /*-------------------------------------------------------------------
12888   MRIreverseSliceOrder() - reverses the order of the slices WITHOUT
12889   changing the gemoetry information. This is specially desgined to
12890   undo the reversal that Siemens sometimes makes to volumes. If
12891   using FreeSurfer unpacking (ie, DICOMRead.c), it should only need
12892   to be done to mosaics. Note: cannot be done in-place!
12893   -------------------------------------------------------------------*/
12894 MRI *MRIreverseSliceOrder(MRI *invol, MRI *outvol)
12895 {
12896   int c,r,s1,s2,f;
12897   double val;
12898 
12899   if(invol == outvol){
12900     printf("ERROR: MRIreverseSliceOrder: cannot be done in-place\n");
12901     return(NULL);
12902   }
12903 
12904   outvol = MRIclone(invol,outvol);
12905 
12906   s2 = invol->depth;
12907   for(s1=0; s1 < invol->depth; s1++){
12908     s2--;
12909     for(c=0; c < invol->width; c++){
12910       for(r=0; r < invol->height; r++){
12911         for(f=0; f < invol->nframes; f++){
12912           val = MRIgetVoxVal(invol,c,r,s1,f);
12913           MRIsetVoxVal(outvol,c,r,s2,f,val);
12914         }
12915       }
12916     }
12917   }
12918 
12919   return(outvol);
12920 }
12921 /*-------------------------------------------------------------------
12922   MRIcopyVolGeomToMRI - copies the volume geometry passed in into the MRI
12923   structure.
12924   -------------------------------------------------------------------*/
12925 int
12926 MRIcopyVolGeomToMRI(MRI *mri, VOL_GEOM *vg)
12927 {
12928   mri->xsize = vg->xsize ;
12929   mri->ysize = vg->ysize ;
12930   mri->zsize = vg->zsize ;
12931   mri->x_r = vg->x_r;
12932   mri->y_r = vg->y_r;
12933   mri->z_r = vg->z_r;
12934   mri->c_r = vg->c_r;
12935   mri->x_a = vg->x_a;
12936   mri->y_a = vg->y_a;
12937   mri->z_a = vg->z_a;
12938   mri->c_a = vg->c_a;
12939   mri->x_s = vg->x_s;
12940   mri->y_s = vg->y_s;
12941   mri->z_s = vg->z_s;
12942   mri->c_s = vg->c_s;
12943   return(NO_ERROR) ;
12944 }
12945 
12946 #define NDIRS 3
12947 static int dirs[NDIRS][3] =
12948   {
12949     { 0, 0, 1},
12950     { 0, 1, 0},
12951     { 1, 0, 0}
12952   } ;
12953 
12954 MRI *
12955 MRInonMaxSuppress(MRI *mri_src, MRI *mri_sup, float thresh, int thresh_dir)
12956 {
12957   int  x, y, z, i, max_i ;
12958   Real val, dx, dy, dz, Ix, Iy, Iz;
12959   Real dot, max_dot, p1_x, p1_y, p1_z, p2_x, p2_y, p2_z;
12960   Real p3_x, p3_y, p3_z, nx, ny, nz, u, xf, yf, zf, oval, numer, denom ;
12961 
12962   mri_sup = MRIcopy(mri_src, mri_sup) ;
12963 
12964   for (x = 0 ; x < mri_src->width ; x++)
12965     {
12966       for (y = 0 ; y < mri_src->height ; y++)
12967         {
12968           for (z = 0 ; z < mri_src->depth ; z++)
12969             {
12970               if (x == Gx && y == Gy && z == Gz)
12971                 DiagBreak() ;
12972               val = MRIgetVoxVal(mri_src, x, y, z,0) ;
12973               val = val*thresh_dir ;
12974               if (val <= thresh)
12975                 {
12976                   MRIsetVoxVal(mri_sup, x, y, z, 0, 0.0) ;
12977                   continue ;
12978                 }
12979               MRIsampleVolumeGradient(mri_src, x, y, z,  &Ix, &Iy, &Iz) ;
12980               dx = dirs[0][0] ; dy = dirs[0][1] ; dz = dirs[0][2] ;
12981               max_i = 0 ;
12982               max_dot = fabs(dx*Ix+dy*Iy+dz*Iz) ;
12983               for (i = 1 ; i < NDIRS ; i++)
12984                 {
12985                   // compute intersection of gradient
12986                   // direction with coordinate planes
12987                   dx = dirs[i][0] ; dy = dirs[i][1] ; dz = dirs[i][2] ;
12988                   dot = fabs(dx*Ix+dy*Iy+dz*Iz) ;
12989                   if (dot > max_dot)
12990                     {
12991                       max_i = i ;
12992                       max_dot = dot ;
12993                     }
12994                 }
12995               // normal to coordinate plane -
12996               // compute intersections of gradient dir with plane
12997               nx = dirs[max_i][0] ;
12998               ny = dirs[max_i][1] ;
12999               nz = dirs[max_i][2] ;
13000               p1_x = x ;    p1_y = y ;    p1_z = z ;    // point on line
13001               p2_x = x+Ix ; p2_y = y+Iy ; p2_z = z+Iz ; // 2nd point on
13002               //                                           gradient line
13003               p3_x = x+nx ; p3_y = y+ny ; p3_z = z+nz ; // point on plane
13004               numer =
13005                 nx * (p3_x - p1_x) +
13006                 ny * (p3_y - p1_y) +
13007                 nz * (p3_z - p1_z) ;
13008               denom =
13009                 nx * (p2_x - p1_x) +
13010                 ny * (p2_y - p1_y) +
13011                 nz * (p2_z - p1_z) ;
13012               if (DZERO(denom))
13013                 {
13014                   DiagBreak() ;
13015                   continue ;
13016                 }
13017               u = numer / denom ;
13018               xf = p1_x + u * Ix ;  yf = p1_y + u * Iy ;  zf = p1_z + u * Iz ;
13019               MRIsampleVolume(mri_src, xf, yf, zf, &oval) ;
13020               oval = oval*thresh_dir ;
13021               if (oval > val)   // not at a maximum
13022                 {
13023                   MRIsetVoxVal(mri_sup, x, y, z, 0, 0) ;
13024                   continue ;
13025                 }
13026               xf = p1_x - u * Ix ;  yf = p1_y - u * Iy ;  zf = p1_z - u * Iz ;
13027               MRIsampleVolume(mri_src, xf, yf, zf, &oval) ;
13028               oval = oval*thresh_dir ;
13029               if (oval > val)   // not at a maximum
13030                 {
13031                   MRIsetVoxVal(mri_sup, x, y, z, 0, 0) ;
13032                   continue ;
13033                 }
13034             }
13035         }
13036     }
13037 
13038   return(mri_sup) ;
13039 }
13040 MRI *
13041 MRIextractRegionAndPad
13042 (MRI *mri_src, MRI *mri_dst, MRI_REGION *region, int pad)
13043 {
13044   MRI *mri_tmp ;
13045   MRI_REGION box ;
13046 
13047   if (region == NULL)
13048     {
13049       region = & box ;
13050       box.x = box.y = box.z = 0 ;
13051       box.dx = mri_src->width ;
13052       box.dy = mri_src->height ;
13053       box.dz = mri_src->depth ;
13054     }
13055   mri_dst =
13056     MRIalloc
13057     (region->dx+2*pad, region->dy+2*pad, region->dz+2*pad, mri_src->type) ;
13058   MRIcopyHeader(mri_src, mri_dst) ;
13059   mri_tmp = MRIextractInto(mri_src, NULL, region->x, region->y, region->z,
13060                            region->dx, region->dy, region->dz, 0, 0, 0) ;
13061   MRIextractInto
13062     (mri_tmp, mri_dst, 0, 0, 0,
13063      region->dx, region->dy, region->dz, pad, pad, pad);
13064   return(mri_dst) ;
13065 }
13066 
13067 MRI *
13068 MRIsetValuesOutsideRegion
13069 (MRI *mri_src, MRI_REGION *region, MRI *mri_dst, float val)
13070 {
13071   int x, y, z ;
13072 
13073   mri_dst = MRIcopy(mri_src, mri_dst) ;
13074 
13075   for (x = 0 ; x < mri_dst->width ; x++)
13076     {
13077       if (x >= region->x && x < region->x+region->dx)
13078         continue ;
13079       for (y = 0 ; y < mri_dst->height ; y++)
13080         {
13081           if (y >= region->y && y < region->y+region->dy)
13082             continue ;
13083           for (z = 0 ; z < mri_dst->depth ; z++)
13084             {
13085               if (z >= region->z && z < region->z+region->dz)
13086                 continue ;
13087               MRIsetVoxVal(mri_dst, x, y, z, 0, val) ;
13088             }
13089         }
13090     }
13091 
13092   return(mri_dst) ;
13093 }
13094 
13095 int
13096 MRIlabelsInNbhd(MRI *mri, int x, int y, int z, int whalf, int label)
13097 {
13098   int xi, yi, zi, xk, yk, zk, count ;
13099 
13100   for (count = 0, zk = -whalf ; zk <= whalf ; zk++)
13101     {
13102       zi = mri->zi[z+zk] ;
13103       for (yk = -whalf ; yk <= whalf ; yk++)
13104         {
13105           yi = mri->yi[y+yk] ;
13106           for (xk = -whalf ; xk <= whalf ; xk++)
13107             {
13108               xi = mri->xi[x+xk] ;
13109               if (MRIvox(mri, xi, yi, zi) == label)
13110                 count++;
13111             }
13112         }
13113     }
13114   return(count) ;
13115 }
13116 

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

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