arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

nrroGinsu.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------
00002 //
00003 //   Joe Kniss
00004 //     6-27-03
00005 //                   ________    ____   ___ 
00006 //                  |        \  /    | /  /
00007 //                  +---+     \/     |/  /
00008 //                  +--+|  |\    /|     < 
00009 //                  |  ||  | \  / |  |\  \ 
00010 //                  |      |  \/  |  | \  \ 
00011 //                   \_____|      |__|  \__\
00012 //                       Copyright  2003 
00013 //                      Joe Michael Kniss
00014 //                   <<< jmk@cs.utah.edu >>>
00015 //               "All Your Base are Belong to Us"
00016 //-------------------------------------------------------------------------
00017 
00018 //nrroGinsu.cpp
00019 
00020 // slice and dice
00021 
00022 #include "nrro.h"
00023 #include "nrroKernel.h"
00024 #include "nrroDispatch.h"
00025 #include <sstream>
00026 #include <typeinfo>
00027 
00028 using namespace gutz;
00029 using namespace std;
00030 
00031 /////////////////////////////////////////////////////////////////////////
00032 // slice
00033 /////////////////////////////////////////////////////////////////////////
00034 NrroSP  Nrro::slice(int axis, int pos)
00035 {
00036    if(!_nrrd)
00037       return NrroSP();
00038 
00039    if(!dim())
00040       return NrroSP();
00041 
00042    Nrrd *nnew = nrrdNew();
00043 
00044    if(_kind & PROXY)
00045    {
00046       nnew->dim = dim() - 1;
00047       int *axesC = new int[dim() -1];
00048       for(int i=0; i<axis; ++i)
00049          axesC[i] = i;
00050       for(int i=axis +1; i< int(dim()) -1; ++i)
00051          axesC[i-1] = i;
00052       
00053 
00054       nnew->data = 0;
00055       nnew->type = _nrrd->type;
00056       nrrdCommentCopy(nnew, _nrrd);
00057    }
00058    else if(nrrdSlice(nnew, _nrrd, axis, pos))
00059    {
00060       char *berr = biffGetDone(NRRD);
00061       NrroErr("slice(), failed", berr);
00062       nrrdNuke(nnew);
00063       return NrroSP();
00064    }
00065 
00066    NrroSP nret(new Nrro(nnew));
00067    nret->setKind(nret->guessKind());
00068 
00069    ostringstream ss;
00070    ss << _name << "_slc" << axis << "-" << pos;
00071    nret->_name = ss.str();
00072 
00073    nret->setModified();
00074    nret->update();
00075    return nret;
00076 }
00077 
00078 /////////////////////////////////////////////////////////////////////////
00079 // crop
00080 /////////////////////////////////////////////////////////////////////////
00081 SmartPtr<Nrro>  Nrro::crop(int min[], int max[])
00082 {
00083    if(!_nrrd)
00084       return NrroSP();
00085 
00086    ///TODO: could make this smart enough to pad
00087    /// where necessary, even though this violates
00088    /// the semantics of "crop"
00089    for(int i=0; i<dim(); ++i)
00090    {
00091       if(min[i] == -1)
00092       {
00093          min[i] = 0;
00094       }
00095       else if(min[i] < 0)
00096       {
00097          NrroErr("crop(), axis min less than 0, should pad this axis");
00098          return NrroSP();
00099       }
00100       if(max[i] == -1)
00101          max[i] = dim(i)-1;
00102       else if(max[i] > int(dim(i))-1)
00103       {
00104          NrroErr("crop(), axis max greater than axis dim, should pad this axis");
00105          return NrroSP();
00106       }
00107    }
00108 
00109    Nrrd *nnew = nrrdNew();
00110    if(nrrdCrop(nnew, _nrrd, min, max))
00111    {
00112       char *berr = biffGetDone(NRRD);
00113       NrroErr("crop(), crop failed", berr);
00114       nrrdNuke(nnew);
00115       return NrroSP();
00116    }
00117    NrroSP nret(new Nrro(nnew));
00118 
00119    nret->setKind(getKind());
00120 
00121    ///make sure the 3D position is still correct.
00122    if(dim() == 3)
00123    {
00124       float xp = float(AIR_AFFINE(0,min[0],dim(0)-1,_pos.x,_pos.x+axisSize(0)));
00125       float yp = float(AIR_AFFINE(0,min[1],dim(1)-1,_pos.y,_pos.y+axisSize(1)));
00126       float zp = float(AIR_AFFINE(0,min[2],dim(2)-1,_pos.z,_pos.z+axisSize(2)));
00127       nret->setPos(vec3f(xp,yp,zp));
00128    }
00129    else if(dim()==4)
00130    {
00131       float xp = float(AIR_AFFINE(0,min[1],dim(1)-1,_pos.x,_pos.x+axisSize(1)));
00132       float yp = float(AIR_AFFINE(0,min[2],dim(2)-1,_pos.y,_pos.y+axisSize(2)));
00133       float zp = float(AIR_AFFINE(0,min[3],dim(3)-1,_pos.z,_pos.z+axisSize(3)));
00134       nret->setPos(vec3f(xp,yp,zp));
00135    }
00136 
00137    /// update the pads so the axisSizeReal is correct
00138    for(int i=0; i<dim(); ++i)
00139    {
00140       if(min[i] < int(_pads[i].x)) // cropped through padded part
00141          nret->_pads[i].x = _pads[i].x - min[i];
00142       else // cropped through real part
00143          nret->_pads[i].x = 0;
00144       if(max[i] > int(_pads[i].y)) //cropped through padded part
00145          nret->_pads[i].y = nret->dim(i) - max[i] - _pads[i].y - 1;
00146       else // cropped through real part
00147          nret->_pads[i].y = nret->dim(i) - 1;
00148    }    
00149 
00150    ostringstream ss;
00151    ss << _name << "_c";
00152    for(int i=0; i<int(dim())-1; ++i)
00153       ss << min[i] << "-" << max[i] << "_";
00154    ss << min[int(dim())-1] << "-" << max[int(dim())-1];
00155    nret->_name = ss.str();
00156   
00157    nret->setModified(); /// forcing an update
00158    nret->update();
00159    return nret;
00160 }
00161 
00162 /////////////////////////////////////////////////////////////////////////
00163 // Pad
00164 /////////////////////////////////////////////////////////////////////////
00165 SmartPtr<Nrro>  Nrro::pad(int min[], int max[], int bound, double padval)
00166 {
00167    if(!_nrrd)
00168       return NrroSP();
00169 
00170    /// TODO: could make this smart enough to crop where needed!
00171    ///  even though this violates the sematics of "pad"
00172    for(int i=0; i<dim(); ++i)
00173    {
00174       if(min[i] > 0)
00175       {
00176          NrroErr("pad(), min setting greater than 0, should crop this axis");
00177          return NrroSP();
00178       }
00179       if(max[i] < int(dim(i))-1)
00180       {
00181          NrroErr("pad(), max setting less than dim of axis, should crop this axis");
00182          return NrroSP();
00183       }
00184    }
00185 
00186    Nrrd *nnew = nrrdNew();
00187    if(nrrdPad_nva(nnew, _nrrd, min, max, bound, padval))
00188    {
00189       char *berr = biffGetDone(NRRD);
00190       NrroErr("pad(), pad failed", berr);
00191       nrrdNuke(nnew);
00192       return NrroSP();
00193    }
00194    NrroSP nret(new Nrro(nnew));
00195 
00196    nret->setKind(getKind());
00197 
00198    /// TODO: shouldn't this handle the pos for back padding?
00199    /// set _pads so we know what part of the data is valid
00200    /// keep the real size correct
00201    for(int i=0; i<dim(); ++i)
00202    {
00203       nret->_pads[i].x = _pads[i].x - min[i];
00204       nret->_pads[i].y = nret->dim(i) - 1 - (max[i] - _pads[i].y);
00205    }    
00206    
00207    ostringstream ss;
00208    ss << _name << "_p_";
00209    for(int i=0; i<int(dim())-1; ++i)
00210       ss << min[i] << "-" << max[i] << "_";
00211    ss << min[int(dim())-1] << "-" << max[int(dim())-1];
00212    nret->_name = ss.str();
00213 
00214    nret->setModified(); /// forcing an update
00215    nret->update();
00216    return nret;
00217 }
00218 
00219 ///////////////////////////////////////////////////
00220 /// pad and or crop to exact size
00221 NrroSP Nrro::cropPad(int min[], int max[], int bound, double padval)
00222 {
00223    if(!_nrrd)
00224       return NrroSP();
00225 
00226    int *cmin = new int[dim()];
00227    int *cmax = new int[dim()];
00228    int *pmin = new int[dim()];
00229    int *pmax = new int[dim()];
00230 
00231    /// figure out sizes for crop and then padd
00232    for(int i=0; i< int(dim()); ++i)
00233    {
00234       /// just clamp the requested dims to the dims of this guy,
00235       /// ie. they must be inside
00236       cmin[i] = clamp(int(0), min[i], int(dim(i))-1);
00237       cmax[i] = clamp(int(0), max[i], int(dim(i))-1);
00238       
00239       /// we croped the lower part of the axis, can't pad
00240       if(cmin[i] > 0)
00241          pmin[i] = 0;
00242       else /// need to pad down
00243          pmin[i] = min[i];
00244    
00245       /// we cropped the upper part of the axis, can't pad
00246       if(cmax[i] < int(dim(i))-1)
00247          pmax[i] = cmax[i] - pmin[i];
00248       else // need to padd up, figure size of croped volume, add difference from original
00249          pmax[i] = cmax[i] - cmin[i] + max[i] - (dim(i)-1);
00250    }
00251 
00252    NrroSP ret = crop(cmin, cmax);
00253    return ret->pad(pmin, pmax, bound, padval);
00254 }
00255 
00256 /////////////////////////////////////////////////////////////////////////
00257 // quantize
00258 /////////////////////////////////////////////////////////////////////////
00259 SmartPtr<Nrro> Nrro::quantize(int bits, double min, double max)
00260 {
00261    if(!_nrrd)
00262       return NrroSP();
00263 
00264    if(min != AIR_NAN)
00265    {
00266       _nrrd->min = min;
00267    }
00268    if(max != AIR_NAN)
00269    {
00270       _nrrd->max = max;
00271    }
00272 
00273    Nrrd *nnew = nrrdNew();
00274 
00275    if(nrrdQuantize(nnew, _nrrd, bits))
00276    {
00277       char *berr = biffGetDone(NRRD);
00278       NrroErr("quantize(), quantize failed", berr);
00279       nrrdNuke(nnew);
00280       return NrroSP();
00281    }
00282    
00283    NrroSP nret(new Nrro(nnew));
00284    nret->_pads = _pads;
00285    nret->_pos = _pos;
00286    nret->_kind = _kind;
00287 
00288    ostringstream ss;
00289    ss << _name << "_q" << bits;
00290    nret->_name = ss.str();
00291  
00292    nret->setModified();  //< forcing an update
00293    nret->update();
00294    return nret;
00295 }
00296 
00297 /////////////////////////////////////////////////////////////////////////
00298 // insert Axis
00299 /////////////////////////////////////////////////////////////////////////
00300 int  Nrro::insertAxis(unsigned int axis)
00301 {
00302    if(!_nrrd)
00303       return 1;
00304 
00305    Nrrd *nnew = nrrdNew();
00306    if(nrrdAxesInsert(nnew, _nrrd, axis))
00307    {
00308       char *berr = biffGetDone(NRRD);
00309       NrroErr("insertAxis(), insert failed", berr);
00310       nrrdNuke(nnew);
00311       return 1;
00312    }
00313    nrrdNuke(_nrrd);
00314    _nrrd = nnew;
00315    for(int i=int(dim())-1; i>int(axis); --i)
00316    {
00317       _pads[i] = _pads[i-1];
00318    }
00319    _pads[axis] = vec2ui(0,0);
00320 
00321    setModified();
00322    update();
00323    return 0;
00324 }
00325 
00326 /////////////////////////////////////////////////////////////////////////
00327 // min max
00328 /////////////////////////////////////////////////////////////////////////
00329 
00330 template<class T>
00331 vec2d minmaxFunc(Nrro::NrroIter<T> ni)
00332 {
00333    if(!ni.isValid()){
00334       cerr << "invalid volume " << typeid(ni).name() 
00335            << " pos = " << ni.pos() << endl;
00336       return vec2d(0,0);
00337    }
00338 
00339    T min = *ni;
00340    T max = *ni;
00341    ++ni;
00342    while(ni.isValid())
00343    {
00344       min = g_min(*ni,min);
00345       max = g_max(*ni,max);
00346       ++ni;
00347    }
00348    return vec2d(double(min),double(max));
00349 }
00350 
00351 void  Nrro::updateMinMax()
00352 {
00353    /// we need a reference to ourselves to use
00354    /// an iterator internally!!!
00355    _incCount();
00356    retDispatchIter1(_minmax,minmaxFunc,this);
00357    _decCount();
00358 
00359    _nrrd->min = _minmax.x;
00360    _nrrd->max = _minmax.y;
00361 }
00362 
00363 /////////////////////////////////////////////////////////////////////////
00364 // resample to specific sizes
00365 /////////////////////////////////////////////////////////////////////////
00366 template<class TO, class TI>
00367 bool nearestResamp(Nrro::NrroIter<TO> nii, Nrro::NrroIter<TI> nio)
00368 {
00369    if(nii->dim() != nio->dim()) return true;
00370 }
00371 
00372 gutz::SmartPtr<Nrro>  Nrro::resample(int dims[], const NrroKernel &kern,
00373                                      int bound, int typeOut)
00374 {
00375    if(!_nrrd)
00376       return NrroSP();
00377 
00378    /// make sure we actually have something to do
00379    bool go = false;
00380 
00381    /// create resample info struct
00382    NrrdResampleInfo *rsmpInfo = nrrdResampleInfoNew();
00383 
00384    /// check statis of all axies compared to dims
00385    for(int i=0; i<int(dim()); ++i)
00386    {
00387       /// if we can do something to this axis, set it up
00388       if(-1 != dims[i])
00389       {
00390          rsmpInfo->kernel[i] = kern.getNrrdKernel();
00391          rsmpInfo->samples[i] = dims[i];
00392          memcpy(rsmpInfo->parm[i], kern.getParams(), 
00393                 (kern.getNrrdKernel())->numParm*sizeof(double));
00394 
00395          if (!AIR_EXISTS(_nrrd->axis[i].min)) {
00396             _nrrd->axis[i].min = 0.0;
00397          }
00398          if (!AIR_EXISTS(_nrrd->axis[i].max)) {
00399             _nrrd->axis[i].max = dim(i) -1;
00400          }
00401 
00402          rsmpInfo->min[i] = _nrrd->axis[i].min;
00403          rsmpInfo->max[i] = _nrrd->axis[i].max;
00404          _nrrd->axis[i].center = nrrdCenterNode;
00405          go = true;
00406       }
00407       /// otherwise we can't change the axis, so mark it so
00408       else
00409       {
00410          rsmpInfo->kernel[i] = 0;
00411       }
00412    }
00413 
00414    rsmpInfo->boundary = bound;
00415    if(typeOut == UNKNOWN)
00416    {
00417       rsmpInfo->type = getType();
00418    }
00419    else
00420    {
00421       rsmpInfo->type = typeOut;
00422    }
00423 
00424    Nrrd *nnew = nrrdNew();
00425    
00426    if(go)
00427    {
00428       if (nrrdSpatialResample(nnew, _nrrd, rsmpInfo)) 
00429       {
00430          char *berr = biffGetDone(NRRD);
00431          NrroErr("resample(), resample failed", berr);
00432          nrrdNuke(nnew);
00433          return NrroSP();
00434       }
00435    }
00436    else
00437    {
00438       if (nrrdCopy(nnew, _nrrd)) 
00439       {
00440          char *berr = biffGetDone(NRRD);
00441          NrroErr("resample(), resample/copy failed", berr);
00442          nrrdNuke(nnew);
00443          return NrroSP();
00444       }
00445    }
00446 
00447    NrroSP nret = new Nrro(nnew);
00448    nret->setKind(nret->guessKind());
00449 
00450    return nret;
00451 }
00452 
00453 /////////////////////////////////////////////////////////////////////////
00454 // resample by some percent
00455 /////////////////////////////////////////////////////////////////////////
00456 gutz::SmartPtr<Nrro>  Nrro::resample(float pct)
00457 {
00458    cerr << " Nrro::resample(float pct) not implemented yet " << endl;
00459    return NrroSP();
00460 }
00461 

Send questions, comments, and bug reports to:
jmk