// template library for multidimensional image processing and analysis // Copyright (C) 2013-2023 Jiri Janacek // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. #if !defined(jil_included) #define jil_included #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include #include #include #include #include #include #include #include #include #ifdef min #undef min #define jil_redefine_min #endif #ifdef max #undef max #define jil_redefine_max #endif //assuming sizeof(size_t)==NumB //assuming sizeof(ptrdiff_t)==NumB //assuming Numb==8*NumB #ifdef _WIN64 #define Numb 64 #define NumB 8 #else #define Numb 32 #define NumB 4 #endif const float max_float= std::numeric_limits::max(); const float max_double= std::numeric_limits::max(); //ConstantsXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX //operations enum UnOpGray {IL_GU_SET, IL_GU_PLUS, IL_GU_MINUS, IL_GU_SUB, IL_GU_MULT, IL_GU_DIV, IL_GU_MAX, IL_GU_MIN, IL_GU_NOT, IL_GU_SQR, IL_GU_POW}; enum UnOpFloat {IL_FU_MULT, IL_FU_DIV, IL_FU_POW}; enum BinOpGray {IL_GB_PLUS, IL_GB_MINUS, IL_GB_SUB, IL_GB_MAX, IL_GB_MULT, IL_GB_DIV, IL_GB_MIN}; enum UnOpBin {IL_BU_SET, IL_BU_NOT}; enum BinOpBin {IL_BB_OR, IL_BB_AND, IL_BB_XOR, IL_BB_DIF, IL_BB_NIF, IL_BB_XORN}; enum UnOpObj {IL_OU_SET, IL_OU_NOT, IL_OU_SQR}; //connectivity enum con2D {con2= 0, con4 = 1, con8}; static inline con2D complement(con2D con) { if (con!=con2) return con2D(3-con); else return con; } enum con3D {con3= 0, con6 = 1, con18, con26}; static inline con3D complement(con3D con) { if ((con!=con3)&&(con!=con18)) return con3D(4-con); else return con; } //resampling method enum resmet {resnear= 0, reslin = 1, rescub = 2}; //thresholding mode enum thrmod {thrgt, thrge, thrlt, thrle, thre}; //reconstruction mode enum recmod {recpart, rectot}; //binary mode enum binmod {binpos, binneg}; //neigbourhood mode enum ngbhsiz {ngbh2= 0, ngbh3}; //math #ifndef SQR static double dsqrarg; #define SQR(a) ((dsqrarg=(a)) == 0.0 ? 0.0 : dsqrarg*dsqrarg) #endif #ifndef M_PI const double M_PI = 3.14159265358979323846; #endif #ifndef M_PI_2 const double M_PI_2 = 1.57079632679489661923; #endif #ifndef M_SQRT2 const double M_SQRT2 = 1.41421356237309504880; #endif #ifndef M_SQRT2_2 const double M_SQRT2_2 = 0.70710678118654752440; #endif //errors class Imgerr { }; //general class Allocerr : public Imgerr { }; //data not allocated class Dimserr : public Imgerr { }; //dimensions do not match class NVarerr : public Imgerr { }; //number of variables do not match class Sizeerr : public Imgerr { }; //sizes do not match class Argerr : public Imgerr { }; //bad argument class Memerr : public Imgerr { }; //memory alloc class Matherr : public Imgerr { }; //bad math operation class Valerr : public Imgerr { }; //too many labels class Numerr : public Imgerr { }; //too few objects //Utilities**************************************************************************** //binary constants const size_t LB = (size_t)(1)<<(Numb-1); const size_t RB = 1; const size_t AB = (size_t)(-1); const ptrdiff_t narr[0x100]= { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8}; static inline ptrdiff_t bitnum(size_t x) { return narr[0xff & x] + narr[0xff & (x>>8)] + narr[0xff & (x>>16)] + narr[0xff & (x>>24)] #ifdef _WIN64 + narr[0xff & (x>>32)] + narr[0xff & (x>>40)] + narr[0xff & (x>>48)] + narr[0xff & (x>>56)] #endif ; } inline ptrdiff_t DimsProd (int nDim0, ptrdiff_t* dims0, int nVars= 1) { ptrdiff_t i, p; for (i= 0, p= 1; i < nDim0; i++) p*= dims0[i]; return p * nVars; } inline ptrdiff_t DimsMax (int nDim0, ptrdiff_t* dims0) { ptrdiff_t p; int i; for (i= 1, p= *dims0; i < nDim0; i++) if (dims0[i] > p) p= dims0[i]; return p; } inline ptrdiff_t DimsProdEx (int nDim0, ptrdiff_t* dims0, int except) { ptrdiff_t p; int i; for (i= 0, p= 1; i < nDim0; i++) if (i != except) p*= dims0[i]; return p; } inline bool DimsEq (int nDim0, ptrdiff_t* dims0, ptrdiff_t* dims1) { int i; bool p= true; for (i= 0; i < nDim0; i++) p&= (dims0[i] == dims1[i]); return p; } inline bool DimsEqEx (int nDim0, ptrdiff_t* dims0, ptrdiff_t* dims1, int except) { int i; bool p= true; for (i= 0; i < nDim0; i++) p&= (i == except) || (dims0[i] == dims1[i]); return p; } inline bool DimsEqProj(int nDim0, ptrdiff_t* dims0, ptrdiff_t* dims1, int dimension) { int i; int j= 0; bool p= true; for (i= 0; i < nDim0; i++) if (i != dimension) p&= (dims0[j++] == dims1[i]); return p; } inline void SetBit(size_t *data, ptrdiff_t index) { ptrdiff_t poloha= (index / Numb); size_t k= LB; k>>= (index % Numb); data[poloha]|= k; } inline bool GetBit(size_t *data, ptrdiff_t index) { ptrdiff_t poloha= (index / Numb); size_t k= LB; k>>= (index % Numb); return ((data[poloha] & k)!= 0); } //3d vectors utilities inline void substvect3d(double x, double y, double z, double *v) { v[0]= x; v[1]= y; v[2]= z; } inline void conv2vect3d(double *x1, double *x2, double a, double *x) { int j; for (j= 0; j < 3; j++) x[j]= a * x1[j] + (1.0 - a) * x2[j]; } inline void copyvect3d(double *u, double *v) { int j; for (j= 0; j < 3; j++) v[j]= u[j]; } inline void normalize3d(double *x) { int j; double s; for (j= 0, s= 0.0; j < 3; j++) s+= x[j] * x[j]; s= sqrt(s); for (j= 0; j < 3; j++) x[j]/= s; } inline void subperp3d(double *x, double *y) { int j; double s; for (j= 0, s= 0.0; j < 3; j++) s+= x[j] * y[j]; for (j= 0; j < 3; j++) x[j]-= s * y[j]; } inline void comb2vect3d(double *x1, double *x2, double a, double b) { int j; for (j= 0; j < 3; j++) x1[j]= a * x1[j] + b * x2[j]; } inline void sub3d(double *x, double *y) { int j; for (j= 0; j < 3; j++) x[j]-= y[j]; } inline void mul3d(double *x, double *y) { int j; for (j= 0; j < 3; j++) x[j]*= y[j]; } inline void vec3d(double *x, double *y) { int j; double s; double value[3]; for (j= 0, s= 0.0; j < 3; j++) value[j]= x[j]; x[0]= value[1] * y[2] - value[2] * y[1]; x[1]= value[2] * y[0] - value[0] * y[2]; x[2]= value[0] * y[1] - value[1] * y[0]; } inline int GetIcosaNum(int divs) { return 5 * divs * divs + 1; } template bool GenIcosaSyst(int divs, double **&y) { const double eps= 1e-6; int num_nodes, vrch; double dp, dq; int i, j, k, p1, r1, s1, p2, r2, p3, r3, p21, r21, p20, r20, s20, t1, t2, t3; double **x; int connec0[60]= { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 1, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 8, 3, 8, 4, 4, 8, 9, 4, 9, 5, 5, 9,10, 5,10, 1, 1,10, 6, 6,11, 7, 7,11, 8, 8,11, 9, 9,11,10,10,11, 6}; int edges[60]= { 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 1, 2, 2, 3, 3, 4, 4, 5, 5, 1, 1,10, 1, 6, 2, 6, 2, 7, 3, 7, 3, 8, 4, 8, 4, 9, 5, 9, 5,10, 6, 7, 7, 8, 8, 9, 9,10,10, 6, 6,11, 7,11, 8,11, 9,11,10,11}; num_nodes= 10 * divs * divs + 2; typedef double *pdouble; x= new pdouble[num_nodes]; if (!x) return false; x[0]= new double[num_nodes * 3]; if (!x[0]) { delete[] x; return false; } for(i= 1; i < num_nodes; i++) x[i]= x[i-1]+3; //vertices substvect3d(0.0, 0.0, 1.0, x[0]); if (divs <= 0) substvect3d(0.0, 0.0, -1.0, x[1]); else { substvect3d(0.0, 0.0, -1.0, x[11]); dp= 1.0 / sqrt(5.0); dq= sqrt(1.0 - dp * dp); for (i= 0; i < 5; i++) { substvect3d(dq * cos(2.0 * M_PI * i / 5.0), dq * sin(2.0 * M_PI * i / 5.0), dp, x[1 + i]); substvect3d(dq * cos(2.0 * M_PI * (i + 0.5) / 5.0), dq * sin(2.0 * M_PI * (i + 0.5) / 5.0), -dp, x[6 + i]); } //edges if (divs > 1) for (i= 0; i < 30; i++) { vrch= 11 + i * (divs - 1); for (j= 1; j < divs; j++) conv2vect3d(x[edges[2 * i + 1]], x[edges[2 * i]], (float)j/(float)divs, x[vrch + j]); } vrch= 12 + 30 * (divs - 1); //planes if (divs > 2) for (i= 0; i < 20; i++) { t1= connec0[3 * i]; t2= connec0[3 * i + 1]; t3= connec0[3 * i + 2]; j= 0; while (!((edges[2 * j] == t1)&&(edges[2 * j + 1] == t2)) &&!((edges[2 * j] == t2)&&(edges[2 * j + 1] == t1))) j++; p1= j; if (edges[2 * p1] == t1) { p3= 1; p2= 12 + p1 * (divs - 1); } else { p3= -1; p2= 12 + (p1 + 1) * (divs - 1) - 1; } j= 0; while (!((edges[2 * j] == t1)&&(edges[2 * j + 1] == t3)) &&!((edges[2 * j] == t3)&&(edges[2 * j + 1] == t1))) j++; r1= j; if (edges[2 * r1] == t1) { r3= 1; r2= 12 + r1 * (divs - 1); } else { r3= -1; r2= 12 + (r1 + 1) * (divs - 1) - 1; } j= 0; while (!((edges[2 * j] == t2)&&(edges[2 * j + 1] == t3)) &&!((edges[2 * j] == t3)&&(edges[2 * j + 1] == t2))) j++; s1= j; p20= p2; r20= r2; s20= vrch; for (j= 2; j < divs; j++) { p21= p2; r21= r2; p2+= p3; r2+= r3; conv2vect3d(x[r2], x[p2], 1.0/(float)j, x[vrch]); vrch++; for (k= 2; k < j; k++) { conv2vect3d(x[r2], x[p2], (float)k/(float)j, x[vrch]); vrch++; } } } } //normalize for (i= 0; i < num_nodes; i++) normalize3d(x[i]); int n_nodes= num_nodes / 2; y= new pdouble[n_nodes]; if (!y) return false; y[0]= new double[n_nodes * 3]; if (!y[0]) { delete[] y; return false; } for(i= 1; i < n_nodes; i++) y[i]= y[i-1]+3; //symmetrize for (i= 0, j= 0; i < num_nodes; i++) if ((x[i][2]>eps)||((fabs(x[i][2])<=eps)&&(x[i][1]>eps)) ||((fabs(x[i][2])<=eps)&&(fabs(x[i][1])<=eps)&&(x[i][0]>0.0))) { if (j >= (num_nodes / 2)) { delete[] x[0]; delete[] x; return false; } copyvect3d(x[i],y[j]); j++; } //clean up delete[] x[0]; delete[] x; return true; } //ClassesXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX class BoundBox { public: double* bounds; int nDim; BoundBox () : bounds (0), nDim (0) { } explicit BoundBox (int nDim0) : bounds (0), nDim (nDim0) { } BoundBox (const BoundBox& x0) { nDim= x0.nDim; bounds= new double[2 * nDim]; SetBounds(x0.bounds); } BoundBox (int nDim0, double* bounds0) { nDim= nDim0; bounds= new double[2 * nDim]; SetBounds(bounds0); } void SetBounds (double* bounds0) { if (!bounds) bounds= new double[2 * nDim]; int i; for (i= 0; i < 2 * nDim; i++) bounds[i]= bounds0[i]; } void SetBounds (float* bounds0) { if (!bounds) bounds= new double[2 * nDim]; int i; for (i= 0; i < 2 * nDim; i++) bounds[i]= bounds0[i]; } double Size (int ndim) const { if (!bounds) return 0.0; return bounds[2 * ndim + 1] - bounds[2 * ndim]; } double Diagonal () const { if (!bounds) return 0.0; int i; double p; for (i= 0, p= 0.0; i < nDim; i++) p+= SQR(bounds[2 * i + 1] - bounds[2 * i]); return sqrt(p); } double Volume () const { if (!bounds) return 0.0; int i; double p; for (i= 0, p= 1.0; i < nDim; i++) p*= bounds[2 * i + 1] - bounds[2 * i]; return p; } void Shift(int ndim, double by) { bounds[2 * ndim]+= by; bounds[2 * ndim + 1]+= by; } void UCrop(int ndim, double by) { bounds[2 * ndim + 1]-= by; } void LCrop(int ndim, double by) { bounds[2 * ndim]+= by; } void Crop(int ndim, double by) { bounds[2 * ndim]+= by; bounds[2 * ndim + 1]-= by; } ~BoundBox () { if (bounds) delete[] bounds; } }; class Frame : public BoundBox { public: ptrdiff_t* dims; Frame () : BoundBox(), dims (0) { } Frame (const Frame& x0) : BoundBox(x0) { dims= new ptrdiff_t[nDim]; SetDims(x0.dims); } Frame (int nDim0, ptrdiff_t* dims0 = 0, double* bounds0 = 0) { nDim= nDim0; bounds= new double[2 * nDim]; dims= new ptrdiff_t[nDim]; int i; if (dims0) SetDims(dims0); else for (i= 0; i < nDim; i++) dims[i]= 1; if (bounds0) SetBounds(bounds0); else for (i= 0; i < nDim; i++) { bounds[2 * i]= 0; bounds[2 * i + 1]= dims[i]; } } double Dx(int i) const { return (bounds[2 * i + 1] - bounds[2 * i]) / dims[i]; } void SetDims (ptrdiff_t* dims0) { if (!dims) dims= new ptrdiff_t[nDim]; int i; for (i= 0; i < nDim; i++) dims[i]= dims0[i]; } void ResetBounds() { int i; for (i= 0; i < nDim; i++) { bounds[2 * i]= 0; bounds[2 * i + 1]= dims[i]; } } ~Frame () { if (dims) delete[] dims; } }; template class Image : public Frame { public: F* data; int nVars; Image () : Frame (), data (0), nVars(1) { } Image (Image& x0) : Frame (x0), data (0), nVars(x0.nVars) { } //overrides default! Image (const Frame& x0, int nVars0 = 1) : Frame (x0), data (0), nVars(nVars0) { } Image (int nDim0, ptrdiff_t* dims0, double* bounds0 = 0, int nVars0 = 1) : Frame(nDim0, dims0, bounds0), data (0), nVars (nVars0) { } void NewData () { if (!data) { ptrdiff_t ndat= DimsProd(nDim, dims, nVars); data= new F[ndat]; if (!data) throw Memerr(); } } void DeleteData () { if (data) delete[] data; data= 0; } templatevoid SetData (G* data0, int step= 1) { if (!data) NewData(); ptrdiff_t ndat= DimsProd(nDim, dims, nVars); F *p= data; G *q= data0; ptrdiff_t i; for (i= 0; i < ndat; i++, p++, q+= step) *p= *q; } templatevoid SetData (G* data0, int step= 1, H mult= 1) { if (!data) NewData(); ptrdiff_t ndat= DimsProd(nDim, dims, nVars); F *p= data; G *q= data0; ptrdiff_t i; for (i= 0; i < ndat; i++, p++, q+= step) *p= *q * mult; } templatevoid SetDataChannel (int channel, G* data0, int step= 1) { if ((channel < 0)||(channel >= nVars)) throw Argerr(); if (!data) NewData(); ptrdiff_t ndat= DimsProd(nDim, dims, 1); F *p= data + channel; G *q= data0; ptrdiff_t i; for (i= 0; i < ndat; i++, p+= nVars, q+= step) *p= *q; } templatevoid GetData (G* data0, int step= 1) { if (!data) throw Allocerr(); ptrdiff_t ndat= DimsProd(nDim, dims, nVars); F *p= data; G *q= data0; ptrdiff_t i; for (i= 0; i < ndat; i++, q+= step, p++) *q= *p; } templatevoid GetDataChannel (int channel, G* data0, int step= 1) { if ((channel < 0)||(channel >= nVars)) throw Argerr(); if (!data) throw Allocerr(); ptrdiff_t ndat= DimsProd(nDim, dims, 1); F *p= data + channel; G *q= data0; ptrdiff_t i; for (i= 0; i < ndat; i++, q+= step, p+= nVars) *q= *p; } void SetData (UnOpGray op = IL_GU_SET, F val = 0) { if (!data) throw Allocerr(); ptrdiff_t ndat= DimsProd(nDim, dims, nVars); F* p= data; ptrdiff_t i; int issigned= std::numeric_limits::is_signed; switch (op) { case IL_GU_SET: for (i= 0; i < ndat; i++, p++) *p= val; break; case IL_GU_PLUS: for (i= 0; i < ndat; i++, p++) *p+= val; break; case IL_GU_MINUS: { if (issigned) for (i= 0; i < ndat; i++, p++) *p-= val; else for (i= 0; i < ndat; i++, p++) if (*p > val) *p-= val; else *p= 0; } break; case IL_GU_SUB: { if (issigned) for (i= 0; i < ndat; i++, p++) *p= val - *p; else for (i= 0; i < ndat; i++, p++) if (*p < val) *p= val - *p; else *p= 0; } break; case IL_GU_MULT: for (i= 0; i < ndat; i++, p++) *p*= val; break; case IL_GU_DIV: for (i= 0; i < ndat; i++, p++) *p/= val; break; case IL_GU_MIN: for (i= 0; i < ndat; i++, p++) if (*p > val) *p= val; break; case IL_GU_MAX: for (i= 0; i < ndat; i++, p++) if (*p < val) *p= val; break; case IL_GU_NOT: { F maxF= (std::numeric_limits::is_integer) ?(std::numeric_limits::max()):(F)0; for (i= 0; i < ndat; i++, p++) *p= maxF - *p; } break; case IL_GU_SQR: for (i= 0; i < ndat; i++, p++) *p= SQR(*p); break; case IL_GU_POW: for (i= 0; i < ndat; i++, p++) *p= pow(double(*p),double(val)); break; } } void SetDataChannel (int channel, UnOpGray op = IL_GU_SET, F val = 0) { if ((channel < 0)||(channel >= nVars)) throw Argerr(); if (!data) throw Allocerr(); ptrdiff_t ndat= DimsProd(nDim, dims, 1); F *p= data + channel; ptrdiff_t i; int issigned= std::numeric_limits::is_signed; switch (op) { case IL_GU_SET: for (i= 0; i < ndat; i++, p+= nVars) *p= val; break; case IL_GU_PLUS: for (i= 0; i < ndat; i++, p+= nVars) *p+= val; break; case IL_GU_MINUS: { if (issigned) for (i= 0; i < ndat; i++, p+= nVars) *p-= val; else for (i= 0; i < ndat; i++, p+= nVars) if (*p > val) *p-= val; else *p= 0; } break; case IL_GU_SUB: { if (issigned) for (i= 0; i < ndat; i++, p+= nVars) *p= val - *p; else for (i= 0; i < ndat; i++, p+= nVars) if (*p < val) *p= val - *p; else *p= 0; } break; case IL_GU_MULT: for (i= 0; i < ndat; i++, p+= nVars) *p*= val; break; case IL_GU_DIV: for (i= 0; i < ndat; i++, p+= nVars) *p/= val; break; case IL_GU_MIN: for (i= 0; i < ndat; i++, p+= nVars) if (*p > val) *p= val; break; case IL_GU_MAX: for (i= 0; i < ndat; i++, p+= nVars) if (*p < val) *p= val; break; case IL_GU_NOT: { F maxF= (std::numeric_limits::is_integer) ?(std::numeric_limits::max()):(F)0; for (i= 0; i < ndat; i++, p+= nVars) *p= maxF - *p; } break; case IL_GU_SQR: for (i= 0; i < ndat; i++, p+= nVars) *p= SQR(*p); break; case IL_GU_POW: for (i= 0; i < ndat; i++, p+= nVars) *p= pow(double(*p),double(val)); break; } } void SetData (UnOpFloat op, double val = 0) { if (!data) throw Allocerr(); ptrdiff_t ndat= DimsProd(nDim, dims, nVars); F* p= data; ptrdiff_t i; int testmax= std::numeric_limits::is_integer; F fmax= std::numeric_limits::max(); switch (op) { case IL_FU_MULT: for (i= 0; i < ndat; i++, p++) { double pf= *p * val; if (testmax && (pf > fmax)) *p= fmax; else *p= pf; } break; case IL_FU_DIV: for (i= 0; i < ndat; i++, p++) { double pf= *p / val; if (testmax && (pf > fmax)) *p= fmax; else *p= pf; } break; case IL_FU_POW: for (i= 0; i < ndat; i++, p++) { double pf= pow(double(*p),val); if (testmax && (pf > fmax)) *p= fmax; else *p= pf; } break; } } void SetDataChannel (int channel, UnOpFloat op, double val = 0) { if ((channel < 0)||(channel >= nVars)) throw Argerr(); if (!data) throw Allocerr(); ptrdiff_t ndat= DimsProd(nDim, dims, 1); F *p= data + channel; ptrdiff_t i; int testmax= std::numeric_limits::is_integer; F fmax= std::numeric_limits::max(); switch (op) { case IL_FU_MULT: for (i= 0; i < ndat; i++, p+= nVars) { double pf= *p * val; if (testmax && (pf > fmax)) *p= fmax; else *p= pf; } break; case IL_FU_DIV: for (i= 0; i < ndat; i++, p+= nVars) { double pf= *p / val; if (testmax && (pf > fmax)) *p= fmax; else *p= pf; } break; case IL_FU_POW: for (i= 0; i < ndat; i++, p+= nVars) { double pf= pow(double(*p),val); if (testmax && (pf > fmax)) *p= fmax; else *p= pf; } break; } } templatevoid SetData (BinOpGray op, G* data0, int step= 1) { if (!data) throw Allocerr(); ptrdiff_t ndat= DimsProd(nDim, dims, nVars); F *p= data; G *q= data0; ptrdiff_t i; int issigned=std::numeric_limits::is_signed; switch (op) { case IL_GB_PLUS: for (i= 0; i < ndat; i++, p++, q+= step) *p+= *q; break; case IL_GB_MINUS: { if (issigned) for (i= 0; i < ndat; i++, p++, q+= step) *p-= *q; else for (i= 0; i < ndat; i++, p++, q+= step) if (*p > *q) *p-= *q; else *p= 0; } break; case IL_GB_SUB: { if (issigned) for (i= 0; i < ndat; i++, p++, q+= step) *p= *q - *p; else for (i= 0; i < ndat; i++, p++, q+= step) if (*p < *q) *p= *q - *p; else *p= 0; } break; case IL_GB_MULT: for (i= 0; i < ndat; i++, p++, q+= step) *p*= *q; break; case IL_GB_DIV: for (i= 0; i < ndat; i++, p++, q+= step) *p/= *q; break; case IL_GB_MAX: for (i= 0; i < ndat; i++, p++, q+= step) if (*p < *q) *p= *q; break; case IL_GB_MIN: for (i= 0; i < ndat; i++, p++, q+= step) if (*p > *q) *p= *q; break; } } templatevoid SetData (BinOpGray op, G* data0, int step= 1, H mult= 1) { if (!data) throw Allocerr(); ptrdiff_t ndat= DimsProd(nDim, dims, nVars); F *p= data; G *q= data0; ptrdiff_t i; int issigned=std::numeric_limits::is_signed; switch (op) { case IL_GB_PLUS: for (i= 0; i < ndat; i++, p++, q+= step) *p+= *q * mult; break; case IL_GB_MINUS: { if (issigned) for (i= 0; i < ndat; i++, p++, q+= step) *p-= *q * mult; else for (i= 0; i < ndat; i++, p++, q+= step) if (*p > (*q * mult)) *p-= *q * mult; else *p= 0; } break; case IL_GB_SUB: { if (issigned) for (i= 0; i < ndat; i++, p++, q+= step) *p= *q * mult - *p; else for (i= 0; i < ndat; i++, p++, q+= step) if (*p < (*q * mult)) *p= *q * mult - *p; else *p= 0; } break; case IL_GB_MULT: for (i= 0; i < ndat; i++, p++, q+= step) *p*= *q * mult; break; case IL_GB_DIV: for (i= 0; i < ndat; i++, p++, q+= step) *p/= *q * mult; break; case IL_GB_MAX: for (i= 0; i < ndat; i++, p++, q+= step) if (*p < (*q * mult)) *p= *q * mult; break; case IL_GB_MIN: for (i= 0; i < ndat; i++, p++, q+= step) if (*p > (*q * mult)) *p= *q * mult; break; } } templatevoid SetDataChannel (int channel, BinOpGray op, G* data0, int step= 1) { if ((channel < 0)||(channel >= nVars)) throw Argerr(); if (!data) throw Allocerr(); ptrdiff_t ndat= DimsProd(nDim, dims, 1); F *p= data + channel; G *q= data0; ptrdiff_t i; int issigned=std::numeric_limits::is_signed; switch (op) { case IL_GB_PLUS: for (i= 0; i < ndat; i++, p+= nVars, q+= step) *p+= *q; break; case IL_GB_MINUS: { if (issigned) for (i= 0; i < ndat; i++, p+= nVars, q+= step) *p-= *q; else for (i= 0; i < ndat; i++, p+= nVars, q+= step) if (*p > *q) *p-= *q; else *p= 0; } break; case IL_GB_SUB: { if (issigned) for (i= 0; i < ndat; i++, p+= nVars, q+= step) *p= *q - *p; else for (i= 0; i < ndat; i++, p+= nVars, q+= step) if (*p < *q) *p= *q - *p; else *p= 0; } break; case IL_GB_MULT: for (i= 0; i < ndat; i++, p+= nVars, q+= step) *p*= *q; break; case IL_GB_DIV: for (i= 0; i < ndat; i++, p+= nVars, q+= step) *p/= *q; break; case IL_GB_MAX: for (i= 0; i < ndat; i++, p+= nVars, q+= step) if (*p < *q) *p= *q; break; case IL_GB_MIN: for (i= 0; i < ndat; i++, p+= nVars, q+= step) if (*p > *q) *p= *q; break; } } double GetAvg(int chan= 0) { ptrdiff_t ndat= DimsProd(nDim, dims, 1); F *p= data + chan; double s; ptrdiff_t i; for (i= 0, s= 0.0; i < ndat; i++, p+= nVars) s+= *p; return s / ndat; } double GetSum(int chan= 0) { ptrdiff_t ndat= DimsProd(nDim, dims, 1); F *p= data + chan; double s; ptrdiff_t i; for (i= 0, s= 0.0; i < ndat; i++, p+= nVars) s+= *p; return s; } double GetSumSq(int chan= 0) { ptrdiff_t ndat= DimsProd(nDim, dims, 1); F *p= data + chan; double s; ptrdiff_t i; for (i= 0, s= 0.0; i < ndat; i++, p+= nVars) s+= SQR(*p); return s; } double GetMax(int chan= 0) { ptrdiff_t ndat= DimsProd(nDim, dims, 1); F *p= data + chan; double maxval= std::numeric_limits::lowest() ; ptrdiff_t i; for (i= 0; i < ndat; i++, p+= nVars) if (*p > maxval) maxval= *p; return maxval; } double GetMin(int chan= 0) { ptrdiff_t ndat= DimsProd(nDim, dims, 1); F *p= data + chan; double minval= max_double ; ptrdiff_t i; for (i= 0; i < ndat; i++, p+= nVars) if (*p < minval) minval= *p; return minval; } }; template class Img : public Image { public: Img () : Image () { } Img (const Img& x0) : Image (x0) { NewData (); } //overrides default! Img (Image& x0) : Image (x0) { NewData (); } Img (const Frame& x0, int nVars0 = 1) : Image (x0, nVars0) { NewData (); } Img (int nDim0, ptrdiff_t* dims0, double* bounds0 = 0, int nVars0 = 1) : Image (nDim0, dims0, bounds0, nVars0) { NewData (); } ~Img () { if (data) delete[] data; } }; class Binary : public Frame { public: size_t* data; Binary () : Frame (), data (0) { } Binary (Binary& x0) : Frame (x0), data (0) { } //overrides default! Binary (const Frame& x0) : Frame (x0), data (0) { } Binary (int nDim0, ptrdiff_t* dims0, double* bounds0 = 0) : Frame(nDim0, dims0, bounds0), data (0) { } void NewData () { if (!data) { ptrdiff_t ndat= (dims[0] + Numb - 1) / Numb * DimsProd(nDim - 1, dims + 1); data= new size_t[ndat]; if (!data) throw Memerr(); } } void DeleteData () { if (data) delete[] data; data= 0; } void EraseEnd () { ptrdiff_t i, ints, height; size_t c, *p; if(data && (dims[0] % Numb)) { c= AB; c>>= (dims[0] % Numb); c= ~c; ints= ((dims[0] + Numb - 1) / Numb); height= DimsProd(nDim - 1, dims + 1); p= data + ints - 1; for(i= 0; i < height; i++, p+= ints) *p&= c; } } int GetEmpty () { ptrdiff_t i, j, ints, height, full; size_t c, *p; full= 0; if(data) { c= AB; c>>= ((dims[0] - 1) % Numb) + 1; c= ~c; ints= ((dims[0] + Numb - 1) / Numb); height= DimsProd(nDim - 1, dims + 1); for (j= 0, p= data; j < height; j++) { for(i= 1; i < ints; i++, p++) full= full || *p; full= full || (*p & c); p++; } } return !full; } ptrdiff_t GetCount() { ptrdiff_t i, j, ints, height, count; size_t c, *p; count= 0; if(data) { c= AB; c>>= ((dims[0] - 1) % Numb) + 1; c= ~c; ints= ((dims[0] + Numb - 1) / Numb); height= DimsProd(nDim - 1, dims + 1); for (j= 0, p= data; j < height; j++) { for(i= 1; i < ints; i++, p++) count+= bitnum(*p); count+= bitnum(*p & c); p++; } } return count; } void GetData (size_t* data0) const { if (!data) return; ptrdiff_t ndat= (dims[0] + Numb - 1) / Numb * DimsProd(nDim - 1, dims + 1); size_t *p, *q; p= data; q= data0; ptrdiff_t i; for (i= 0; i < ndat; i++, p++, q++) *q= *p; } void SetData (size_t* data0) { if (!data) NewData(); ptrdiff_t ndat= (dims[0] + Numb - 1) / Numb * DimsProd(nDim - 1, dims + 1); size_t *p, *q; p= data; q= data0; ptrdiff_t i; for (i= 0; i < ndat; i++, p++, q++) *p= *q; } void SetData (UnOpBin op = IL_BU_SET, int val = 0) { if (!data) throw Allocerr(); ptrdiff_t ndat= (dims[0] + Numb - 1) / Numb * DimsProd(nDim - 1, dims + 1); size_t *p; p= data; ptrdiff_t i; switch (op) { case IL_BU_SET: if (val) { for (i= 0; i < ndat; i++) *(p++)= AB; EraseEnd(); } else for (i= 0; i < ndat; i++) *(p++)= 0; break; case IL_BU_NOT: { for (i= 0; i < ndat; i++) *(p++)= ~*p; EraseEnd(); } } } void SetData (BinOpBin op, size_t* data0) { if (!data) throw Allocerr(); ptrdiff_t ndat= (dims[0] + Numb - 1) / Numb * DimsProd(nDim - 1, dims + 1); size_t *p, *q; p= data; q= data0; ptrdiff_t i; switch (op) { case IL_BB_OR: for (i= 0; i < ndat; i++, p++, q++) *p|= *q; break; case IL_BB_AND: for (i= 0; i < ndat; i++, p++, q++) *p&= *q; break; case IL_BB_XOR: { for (i= 0; i < ndat; i++, p++, q++) *p^= *q; EraseEnd(); } break; case IL_BB_DIF: for (i= 0; i < ndat; i++, p++, q++) *p&= ~*q; break; case IL_BB_NIF: for (i= 0; i < ndat; i++, p++, q++) *p|= ~*q; break; case IL_BB_XORN: { for (i= 0; i < ndat; i++, p++, q++) *p^= ~*q; EraseEnd(); } } } }; class Bin : public Binary { public: Bin () : Binary () { } Bin (const Bin& x0) : Binary (x0) { NewData (); } //overrides default! Bin (Binary& x0) : Binary (x0) { NewData (); } Bin (const Frame& x0) : Binary (x0) { NewData (); } Bin (int nDim0, ptrdiff_t* dims0, double* bounds0 = 0) : Binary (nDim0, dims0, bounds0) { NewData (); } ~Bin () { if (data) delete[] data; } }; class Object { public: Object() : nVar (0) , data (0) { } Object(const Object& x0) : nVar (x0.nVar) { data= new double[nVar]; int i; for (i= 0; i < nVar; i++) data[i]= x0.data[i]; } explicit Object(int nVar0) : nVar (nVar0) { data= new double[nVar]; } templateObject(int nVar0, G* data0) : nVar (nVar0) { data= new double[nVar]; double *p; G *q; p= data; q= data0; int i; for (i= 0; i < nVar; i++) *(p++)= *(q++); } Object& operator=(const Object& x0) { if (!data || nVar != x0.nVar) { nVar= x0.nVar; if (data) delete data; data= new double[nVar]; } int i; for (i= 0; i < nVar; i++) data[i]= x0.data[i]; return *this; } templatevoid SetData (G* data0, int num = nVar) { if (!data) data= new double[nVar]; if (num > nVar) num= nVar; double *p; G *q; p= data; q= data0; int i; for (i= 0; i < num; i++) *(p++)= *(q++); } double Dist(const Object& arg, int nDim) { if (!data) return 0.0; double sum= 0.0; int i; for (i= 0; i < nDim; i++) { double pom= data[i] - arg.data[i]; sum+= pom * pom; } return sqrt(sum); } double operator[](int i) const { return data[i]; } double& operator[](int i) { return data[i]; } ~Object() { if (data) delete [] data; } int nVar; double* data; }; typedef std::vector ObjectArray; //TODO class - nDim test, BBox op inline void SetData(ObjectArray &objs, int chan, UnOpObj op) { ptrdiff_t ndat= objs.size(); double s; ptrdiff_t i; switch(op) { case IL_OU_SET: for (i= 0; i < ndat; i++) { Object &po= objs[i]; po[chan]= 0.; } break; case IL_OU_NOT: for (i= 0; i < ndat; i++) { Object &po= objs[i]; po[chan]= - po[chan]; } break; case IL_OU_SQR: for (i= 0; i < ndat; i++) { Object &po= objs[i]; po[chan]= SQR(po[chan]); } break; } } inline double GetAvg(ObjectArray &objs, int chan) { ptrdiff_t ndat= objs.size(); double s; ptrdiff_t i; for (i= 0, s= 0.0; i < ndat; i++) { Object &po= objs[i]; s+= po[chan]; } return s / ndat; } inline double GetSum(ObjectArray &objs, int chan) { ptrdiff_t ndat= objs.size(); double s; ptrdiff_t i; for (i= 0, s= 0.0; i < ndat; i++) { Object &po= objs[i]; s+= po[chan]; } return s; } inline double GetMax(ObjectArray &objs, int chan) { ptrdiff_t ndat= objs.size(); double pmax= std::numeric_limits::lowest(); ptrdiff_t i; for (i= 0; i < ndat; i++) { Object &po= objs[i]; if (po[chan] > pmax) pmax= po[chan]; } return pmax; } inline int GetArgMax(ObjectArray &objs, int chan) { ptrdiff_t ndat= objs.size(); double pmax= std::numeric_limits::lowest(); ptrdiff_t imax= -1; ptrdiff_t i; for (i= 0; i < ndat; i++) { Object &po= objs[i]; if (po[chan] > pmax) { pmax= po[chan]; imax= i; } } return imax; } inline double GetMin(ObjectArray &objs, int chan) { ptrdiff_t ndat= objs.size(); double pmin= max_double; ptrdiff_t i; for (i= 0; i < ndat; i++) { Object &po= objs[i]; if (po[chan] < pmin) pmin= po[chan]; } return pmin; } inline int GetArgMin(ObjectArray &objs, int chan) { ptrdiff_t ndat= objs.size(); double pmin= max_double ; ptrdiff_t imin= -1; ptrdiff_t i; for (i= 0; i < ndat; i++) { Object &po= objs[i]; if (po[chan] < pmin) { pmin= po[chan]; imin= i; } } return imin; } inline void SelectObjects(ObjectArray& I, ObjectArray& O, int index, double value, thrmod thr = thrgt) { for (ObjectArray::iterator io = I.begin (); io != I.end (); io++) { #define CASE(OP) \ if ((*io)[index] OP value) O.push_back(*io); \ break; switch (thr) { case thrgt: CASE(>) case thrge: CASE(>=) case thrlt: CASE(<) case thrle: CASE(<=) case thre: CASE(==) } } } #undef CASE inline void ShiftObjects(ObjectArray& I, int index, double value) { for (ObjectArray::iterator io = I.begin (); io != I.end (); io++) (*io)[index]+= value; } inline void PrintObjects(ObjectArray& I, int index) { for (ObjectArray::iterator io = I.begin (); io != I.end (); io++) printf("%g ",(*io)[index]); printf("\n"); fgetchar(); } typedef std::vector ObjectArrayArray; //DeclarationsXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX //slice template Frame* SliceFrame (const Frame& I, const int dimension); template void SliceData (Image& I, Image& O, const int dimension, const ptrdiff_t index); template Image* Slice (Image& I, const int dimension, const ptrdiff_t index); //projection template void ProjectionData (Image& I, Image& O, const int dimension); template Image* Projection (Image& I, const int dimension); //crop template Frame* CropFrame (const Frame& I, const BoundBox& J); template void CropData (Image& I, const Frame& J, Image& O); template Image* Crop (Image& I, const BoundBox& J, double val /*=0*/); //paint template void PaintData (Image& I, Image& J); //calibration constant from I, start from BBox J //resampling template Frame* Resample1DFrame (const Frame& I, const int dimension, const double factor); template Frame* Resample1DFrame (const Frame& I, const int dimension, const Frame& B); template void Resample1DData (Image& I, Image& O, const int dimension, const resmet method /*=reslin*/); template Image* Resample1D (Image& I, const int dimension, const double factor, const resmet method /*=reslin*/); template Image* Resample1D (Image& I, const int dimension, const Frame& B, const resmet method /*=reslin*/); template Frame* ResampleFrame (const Frame& I, const int dimension, const double factor); template Frame* ResampleFrame (const Frame& I, const int dimension, const Frame& B); template void ResampleData (Image& I, Image& O, const int dimension, const resmet method /*=reslin*/); template Image* Resample (Image& I, const int dimension, const double factor, const resmet method /*=reslin*/); template Image* Resample (Image& I, const int dimension, const Frame& B, const resmet method /*=reslin*/); template void Shift1D (Image& I, const int dimension, const double by, double val /*=0*/, const resmet method /*=reslin*/); template void Shift2D (Image& I, const double sx, const double sy, double val /*=0*/, const resmet method /*=reslin*/); template void Shift3D (Image& I, const double sx, const double sy, const double sz, double val /*=0*/, const resmet method /*=reslin*/); //rotation and shift in 2d template void Rot2D (Image& I, const double dx, const double dy, const double sx, const double sy, const double angle, double val /*=0*/, const resmet method /*=reslin*/); template void Rot3DPlane (Image& I, const int plane, const double dx, const double dy, const double sx, const double sy, const double angle, double val /*= 0*/, resmet method /*= reslin*/); template void Rot3DPlanePi (Image& I, const int plane); //morphology in 1d, 2d and 3d template void Dilate1D (Image& I, int num); template void Erode1D (Image& I, int num); template void MorphGrad1D(Image& I); template void Close1D (Image& I, int num); template void Open1D (Image& I, int num); template void Dilate2D (Image& I, int num); template void Erode2D (Image& I, int num); template void MorphGrad2D(Image& I); template void Close2D (Image& I, int num); template void Open2D (Image& I, int num); template void Dilate3D (Image& I, int num); template void Erode3D (Image& I, int num); template void MorphGrad3D(Image& I); template void Close3D (Image& I, int num); template void Open3D (Image& I, int num); template void Dilate2D3D (Image& I, int num2, int num3); template void Erode2D3D (Image& I, int num2, int num3); template void Close2D3D (Image& I, int num2, int num3); template void Open2D3D (Image& I, int num2, int num3); template void Dilate1D3D (Image& I, int num2, int num3); template void Erode1D3D (Image& I, int num2, int num3); template void Close1D3D (Image& I, int num2, int num3); template void Open1D3D (Image& I, int num2, int num3); //line and surface morphology in 2d and 3d template void Dilate2DLin (Image& I, int num, double angle); //angle 0 to M_PI template void Erode2DLin (Image& I, int num, double angle); template void Close2DLin (Image& I, int num, double angle); template void Open2DLin (Image& I, int num, double angle); template void Dilate2DLinN (Image& I, int num, int steps, double angle0 /*=0.0*/); template void Erode2DLinN (Image& I, int num, int steps, double angle0 /*=0.0*/); template void Close2DLinN (Image& I, int num, int steps, double angle0 /*=0.0*/); template void Open2DLinN (Image& I, int num, int steps, double angle0 /*=0.0*/); template void Dilate2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0 /*=0.0*/); template void Dilate2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0 /*=0.0*/); template void Erode2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0 /*=0.0*/); template void Erode2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0 /*=0.0*/); template void Close2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0 /*=0.0*/); template void Close2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0 /*=0.0*/); template void Open2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0 /*=0.0*/); template void Open2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0 /*=0.0*/); //lattitude from -M_PI/2 to M_PI/2, longitude from 0 to 2*M_PI template void Dilate3DLin (Image& I, int num, double lattitude, double longitude); template void Erode3DLin (Image& I, int num, double lattitude, double longitude); template void Close3DLin (Image& I, int num, double lattitude, double longitude); template void Open3DLin (Image& I, int num, double lattitude, double longitude); template void Dilate3DLinN (Image& I, int num, int steps, double lattitude0 /*=0.0*/, double longitude0 /*=0.0*/); template void Erode3DLinN (Image& I, int num, int steps, double lattitude0 /*=0.0*/, double longitude0 /*=0.0*/); template void Close3DLinN (Image& I, int num, int steps, double lattitude0 /*=0.0*/, double longitude0 /*=0.0*/); template void Open3DLinN (Image& I, int num, int steps, double lattitude0 /*=0.0*/, double longitude0 /*=0.0*/); template void Dilate3DSurf (Image& I, int num, double lattitude, double longitude); template void Erode3DSurf (Image& I, int num, double lattitude, double longitude); template void Close3DSurf (Image& I, int num, double lattitude, double longitude); template void Open3DSurf (Image& I, int num, double lattitude, double longitude); template void Dilate3DSurfN(Image& I, int num, int steps, double lattitude0 /*=0.0*/, double longitude0 /*=0.0*/); template void Erode3DSurfN (Image& I, int num, int steps, double lattitude0 /*=0.0*/, double longitude0 /*=0.0*/); template void Close3DSurfN (Image& I, int num, int steps, double lattitude0 /*=0.0*/, double longitude0 /*=0.0*/); template void Open3DSurfN (Image& I, int num, int steps, double lattitude0 /*=0.0*/, double longitude0 /*=0.0*/); //Lipschitz (grayscale opening by a cone) in 2d and 3d, with labelling, TODO 1d template void Lipschitz2D (Image& I, double slope, int dir); template void LipschitzRec2D (Image& I, double slope, int dir, con2D conn /*= con4*/, recmod rec /*= rectot*/); template void LipschitzTopHat2D(Image& I, double slope, int dir); template void LipschitzTopHatRec2D (Image& I, double slope, int dir, con2D conn /*= con4*/, recmod rec /*= rectot*/); template void Lipschitz2D (Image& I, Image*& L, double slope, int dir); template void Lipschitz3D (Image& I, double slope, int dir); template void LipschitzRec3D (Image& I, double slope, int dir, con3D conn /*= con6*/, recmod rec /*= rectot*/); template void LipschitzTopHat3D(Image& I, double slope, int dir); template void LipschitzTopHatRec3D (Image& I, double slope, int dir, con3D conn /*= con6*/, recmod rec /*= rectot*/); template void Lipschitz3D (Image& I, Image*& L, double slope, int dir); //Gaussian smooth, recursive implementation for sigma > dx template void Gauss1D (Image& I, int dimension, double sigma); template void Gauss (Image& I, int ndim, double sigma); //Laplace, TODO 1d template void Laplace2D (Image& I); template void Laplace3D (Image& I); template void Laplace(Image& I, Image& O, int ndim); //lin moving average filters, G is buffer type, must be able to hold n*maxF template void MovAvg2DLin (Image& I, int num, double angle); template void MovAvg2DLin (Image& I, int num, double angle); template void MovAvg3DLin (Image& I, int num, double lattitude, double longitude); template void MovAvg3DLin (Image& I, int num, double lattitude, double longitude); template void MovAvg3DSurf (Image& I, int num, double lattitude, double longitude); template void MovAvg3DSurf (Image& I, int num, double lattitude, double longitude); //gradient, TODO 1d template void Gradient2D (Image& I, Image& J, ngbhsiz siz /*= ngbh3*/, double mult /*= 1.0*/); template void Gradient2DAbs (Image& I, Image& J, ngbhsiz siz /*= ngbh3*/, double mult /*= 1.0*/); template void Gradient2DAbsVec (Image& I, Image& J, Image& V, ngbhsiz siz /*= ngbh3*/, double mult /*= 1.0*/); template void Gradient2DAbsTen (Image& I, Image& J, Image& T, ngbhsiz siz /*= ngbh3*/, double mult /*= 1.0*/); template void Gradient2DTen (Image& I, Image& J, ngbhsiz siz /*= ngbh3*/, double mult /*= 1.0*/); template void Gradient3D (Image& I, Image& J, ngbhsiz siz /*= ngbh3*/, double mult /*= 1.0*/); template void Gradient3DAbs (Image& I, Image& J, ngbhsiz siz /*= ngbh3*/, double mult /*= 1.0*/); template void Gradient3DAbsVec (Image& I, Image& J, Image& V, ngbhsiz siz /*= ngbh3*/, double mult /*= 1.0*/); template void Gradient3DAbsTen (Image& I, Image& J, Image& T, ngbhsiz siz /*= ngbh3*/, double mult /*= 1.0*/); template void Gradient3DTen (Image& I, Image& J, ngbhsiz siz /*= ngbh3*/, double mult /*= 1.0*/); //curvature based filters for feature enhancement, TODO 1d template void Curvature2DMax (Image& I, Image& J, int discr /*= 0*/, double mult /*= 1.0*/); template void Curvature2DMaxTen (Image& I, Image& J, Image& T, int discr /*= 0*/, double mult /*= 1.0*/); template void Curvature2DTen (Image& I, Image& T, double mult /*= 1.0*/); template void Curvature2DVec (Image& I, Image& T, double mult /*= 1.0*/); template void Curvature2DMaxVec (Image& I, Image& J, Image& T, double /*mult= 1.0*/); template void Curvature3DMax (Image& I, Image& J, int discr /*= 0*/, double mult /*= 1.0*/); template void Curvature3DMaxTen (Image& I, Image& J, Image& T, int discr /*= 0*/, double mult /*= 1.0*/); template void Curvature3DTen (Image& I, Image& T, double mult /*= 1.0*/); //reconstruction in 1d, 2d and 3d, I under J template void Reconstruct1D(Image& I, Image& J); template void Reconstruct2D(Image& I, Image& J, con2D conn /*= con4*/, recmod rec /*= rectot*/); template void Reconstruct3D(Image& I, Image& J, con3D conn /*= con6*/, recmod rec /*= rectot*/); //watershed transform in 2d and 3d template void Watershed2D(Image& I, Image& J, con2D conn/*= con4*/); template void Watershed2D(Image& I, Image& J, con2D conn/* = con4*/); template void Watershed3D(Image& I, Image& J, con3D conn/*= con6*/); template void Watershed3D(Image& I, Image& J, con3D conn/* = con6*/); //area and volume opening in 2d and 3d, TODO 1d template void OpenArea2D (Image& I, const ptrdiff_t minsize, con2D conn, int dir); template void OpenAreaTopHat2D (Image& I, const ptrdiff_t minsize, con2D conn, int dir); template void OpenVolume3D (Image& I, const ptrdiff_t minsize, con3D conn, int dir); template void OpenVolumeTopHat3D (Image& I, const ptrdiff_t minsize, con3D conn, int dir); //median filter in 2d and 3d template void MedianFilter2D (Image& I, const ptrdiff_t size); //template void MedianFilter2D (Image& I, const ptrdiff_t size); template void MedianFilter3D (Image& I, const ptrdiff_t size, const ptrdiff_t sizez); //template void MedianFilter3D (Image& I, const ptrdiff_t size, const ptrdiff_t sizez); //drawing points and lines template void Points (Image& I, Object& O); template void Points (Image& I, ObjectArray& O); template void Polyline (Image& I, ObjectArray& O); template void Segments (Image& I, ObjectArray& O); //threshold: B= I >,>=,<,<= value; template void Threshold (Image& I, Binary& B, const F value, thrmod thr /* = thrgt*/); //B= value1<= I < value2; template void Threshold (Image& I, Binary& B, const F value1, const F value2); //combine: if B I=J template void Combine (Image& I, Binary& B, Image& J, binmod mode /* = binpos*/); template void Combine (Image& I, Binary& B, const G val, binmod mode /* = binpos*/); //binary morphology in 2d and 3d, TODO 1d template void Dilate2DBin (Binary& I, int num); template void Dilate2DBin8 (Binary& I); template void Erode2DBin (Binary& I, int num); template void Erode2DBin8 (Binary& I); template void Boundary2DBin(Binary& I); template void Close2DBin (Binary& I, int num); template void Open2DBin (Binary& I, int num); template void Dilate3DBin (Binary& I, int num); template void Dilate3DBin10(Binary& I); template void Dilate3DBin18(Binary& I); template void Erode3DBin (Binary& I, int num); template void Erode3DBin10 (Binary& I); template void Erode3DBin18 (Binary& I); template void Boundary3DBin(Binary& I); template void Close3DBin (Binary& I, int num); template void Open3DBin (Binary& I, int num); template void Dilate2D3DBin(Binary& I, int num2, int num3); template void Erode2D3DBin (Binary& I, int num2, int num3); template void Close2D3DBin (Binary& I, int num2, int num3); template void Open2D3DBin (Binary& I, int num2, int num3); template void Dilate1D3DBin(Binary& I, int num2, int num3); template void Erode1D3DBin (Binary& I, int num2, int num3); template void Close1D3DBin (Binary& I, int num2, int num3); template void Open1D3DBin (Binary& I, int num2, int num3); //thinning, skeleton template void Skeleton2DBin (Binary& I, int num /*= -1*/, con2D conn /*=con8*/); template void Thin2DBin (Binary& I, int num /*= -1*/, con2D conn /*=con8*/); template void Prune2DBin (Binary& I, int num /*= -1*/, con2D conn /*=con8*/); template void EndPoints2DBin (Binary& I, con2D conn /*=con8*/); template void MidPoints2DBin (Binary& I, con2D conn /*=con8*/); template void Skeleton3DBin (Binary& I, int num /*= -1*/, con3D conn /*=con26*/); template void Skeleton3DBin (Binary& I, Binary& J, int num /*= -1*/, con3D conn /*=con26*/); template void Thin3DBin (Binary& I, int num /*= -1*/, con3D conn /*=con26*/); template void Prune3DBin (Binary& I, int num /*= -1*/, con3D conn /*=con26*/); template void EndPoints3DBin (Binary& I, con3D conn /*=con26*/); template void MidPoints3DBin (Binary& I, con3D conn /*=con26*/); //conditional dilation in 1d, 2d and 3d, TODO 1d clean a holes template void Reconstruct1DBin (Binary& I, Binary& J); template void Reconstruct2DBin (Binary& I, Binary& J, con2D con /*= con4*/); template void Reconstruct3DBin (Binary& I, Binary& J, con3D con /*= con6*/); template void Clean2DBin (Binary& I, int num, con2D con /*= con4*/); template void Clean2D3DBin (Binary& I, int num2, int num3, con3D /*con = con18*/); template void FillHoles2DBin (Binary& I, con2D con /*= con4*/); template void FillHoles3DBin (Binary& I, con3D /*con = con18*/); template void Clean2DBinSize (Binary& I, int num, con2D con /*= con4*/, thrmod tmod/* = thrge*/); template void Clean3DBinSize (Binary& I, int num, con3D con /*=con18*/, thrmod tmod/* = thrge*/); //TODO: correct skeleton3d //binary drawing template void PointsBin (Binary& I, ObjectArray& O); template void PolylineBin (Binary& I, ObjectArray& O, bool clip /*=true*/); template void PolylinesBin (Binary& I, ObjectArrayArray& O, bool clip /*=true*/); template void SegmentsBin (Binary& I, ObjectArray& O, bool clip /*=true*/); template void Polygon2DBin (Binary& I, ObjectArray& O, bool clip /*=true*/); template void Polygons2DBin (Binary& I, ObjectArrayArray& O, bool clip /*=true*/); template void Triangle3DBin (Binary& I, ObjectArray& O); template void Triangles3DBin (Binary& I, ObjectArrayArray& O); //binary measurements, TODO 1d //template void Measure1D (Binary& I, double& Length, double& EulerNo); template void Measure2D (Binary& I, double& Area, double& Perimeter, double& EulerNo); template void Euler2D (Binary& I, double& EulerNo4, double& EulerNo6, double& EulerNo8); template void Measure3D (Binary& I, double& Volume, double& Surface, double& Length, double& EulerNo); template void Measure3D3 (Binary& I, double& Volume, double& Surface, double& Length, double& EulerNo, float* rosea/* = NULL*/, float* rosel/* = NULL*/); template void Euler3D (Binary& I, double& EulerNo6, double& EulerNo18, double& EulerNo26); //binary erase boundary objects in 2d and 3d, TODO 1d template void EraseBoundary2DBin (Binary& I, con2D conn /*=con8*/); template void EraseBoundary3DBin (Binary& I, con3D conn /*=con18*/); //labeled boundary to bin, TODO 1d template void Label2DBin(Image& I, Binary& image, ptrdiff_t count); template void Label3DBin(Image& I, Binary& image, ptrdiff_t count); //resampling binary to byte, TODO 1d template Image* BinResample2D (Binary& I, const int xy); template Image* BinResample3D (Binary& I, const int xy, const int z); //local maxima in 1d, 2d and 3d template void Maxima1D (Image& I, Binary& B, const F value); template void Maxima1D (Image& I, Binary& B, const F value1, const F value2); template void Maxima2D (Image& I, Binary& B, const F value, con2D conn); template void Maxima2D (Image& I, Binary& B, const F value1, const F value2, con2D conn); template void Maxima3D (Image& I, Binary& B, const F value, con3D conn); template void Maxima3D (Image& I, Binary& B, const F value1, const F value2, con3D conn); //labelling and objects measurement in 1d, 2d and 3d, TODO 1d labeling template void MeasureObjects1DBin(Binary& I, ObjectArray& O); template void Label2D(Binary& image, Image& I, con2D conn, F& val); template void LabelObjects2D(Image& I, Image& J, bool bconst /*= false*/); template void MeasureObjects2DBin(Binary& I, ObjectArray& O, con2D con /*= con4*/); template void MeasureObjects2D(Image& I, ObjectArray& O); template void MeasureObjects2D(Image& I, Image& J, ObjectArray& O); template void MeasureObjects2D(Image& I, Image& J, F& val, ObjectArray& O); template void MeasureObjects2D(Image& I, F& val, ObjectArray& O); template void MeasureObjects2D(Image& I, Image& J, F& val, ObjectArray& O); template void Label3D(Binary& image, Image& I, con3D conn, F& val); template void LabelObjects3D(Image& I, Image& J, bool bconst /*= false*/); template void MeasureObjects3DBin(Binary& I, ObjectArray& O, con3D con /*= con6*/); template void MeasureObjects3D(Image& I, ObjectArray& O); template void MeasureObjects3D(Image& I, Image& J, ObjectArray& O); template void MeasureObjects3D(Image& I, F& val, ObjectArray& O); template void MeasureObjects3D(Image& I, Image& J, F& val, ObjectArray& O); template void MeasureG (Binary& B, Image& I, ptrdiff_t &Num, double &Mean); //distance transform template void DistanceData (Binary& I, Image& O, const int dimensionality, bool dosqrt /*= true*/); template Image* Distance (Binary& I, const int dimensionality, bool dosqrt /*= true*/); template void DistancePower (Image& IO, const int dimensionality, bool dosqrt /*= true*/); template void Mosaic (Image& I, const int dimensionality); template void DistanceMosaic (Image& I, Image& O, const int dimensionality, const int mode /*=0*/); template void DistanceMosaicPower (Image& L, Image& IO, const int dimensionality, bool dosqrt /*= true*/); template void DistanceGeodesic2D (Binary& I, Binary& M, Image& O); template void DistanceGeodesic3D (Binary& I, Binary& M, Image& O); //line to objects template void LineProfile(Image& I, Object& x1i, Object& x2i, ObjectArray& O); //voxels to objects template void Voxels(Image& I, ObjectArray& O); template void VoxelsBin(Binary& I, ObjectArray& O); //bounding box template void BBox(Image& I, BoundBox& bb); template void BBoxBin(Binary& I, BoundBox& bb); //evaluating objects template void EvaluateObjects(Image& I, ObjectArray& L, ObjectArray& O); template ptrdiff_t EvaluateObject(Image& I, Object& O); //masking objects template void MaskObjects(Binary& J, ObjectArray& I, ObjectArray& O); //objects selection, duplicate template void SelectObjects(ObjectArray& I, ObjectArray& O, int index, double value, thrmod thr /*= thrgt*/); //objects shift, duplicate template void ShiftObjects(ObjectArray& I, int index, double value); template void TraceObjects2DBin(Binary& I, ObjectArrayArray& O, bool holes, bool at_bound, con2D con /*= con4*/); template void TraceObjects2D(Image& I, ObjectArrayArray& O, F minp /*= 0*/, con2D con /*= con4*/); //ImplementationXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX //array of byte bitcounts /* template void initbitnum(int* narr) { int i, j, k, l; for(i= 0; i < 0x100; i++) { k= 0; l= 1; for(j= 0; j < 8; j++, l<<= 1) if(i & l) k++; narr[i]= k; } } */ template void choldc(double **a, int n, double *p) { int i, j, k; double sum; for (i= 0; i < n; i++) { for (j= i; j < n; j++) { for (sum= a[i][j], k= i - 1; k >= 0; k--) sum-= a[i][k] * a[j][k]; if (i == j) { if (sum <= 0.0) { throw Matherr(); } p[i]= sqrt(sum); } else a[j][i]= sum / p[i]; } } } template void cholsl(double **a, int n, double *p, double *b, double *x) { int i, k; double sum; for (i= 0; i < n; i++) { for (sum= b[i], k= i - 1; k >= 0; k--) sum-= a[i][k] * x[k]; x[i]= sum / p[i]; } for (i= n - 1; i >= 0; i--) { for (sum= x[i], k= i + 1; k < n; k++) sum-= a[k][i] * x[k]; x[i]= sum / p[i]; } } //Bin morphology 2D 3D*************************************************************************** #define INIT \ numint= (width + Numb - 1) / Numb; \ c= ((width % Numb) == 0)?(AB):(AB << (Numb - (width % Numb))); template void dilate2D_0_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *q1, *q2, a, b, c; ptrdiff_t numint, i, j; INIT if (numint == 1) { p2= input; q2= output; #define PROC(x) \ x= *p2 & c; \ x|= x << 1; PROC(a) for (j= 1; j < height; j++) { p2+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; #undef PROC } else if (numint > 1) { p1= input; q1= output; for (i=1 ; i < numint ; i++) { p3= p1 + 1; p2= p1; q2= q1; #define PROC(x) \ x= *p2; \ x|= ((*p3 & LB) != 0)?(RB | (x << 1)):( x << 1); PROC(a) for (j= 1; j < height; j++) { p2+= numint; p3+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } #undef PROC *q2= a; p1++; q1++; } p2= p1; q2= q1; #define PROC(x) \ x= *p2 & c; \ x|= ( x << 1); PROC(a) for (j= 1; j < height; j++) { p2+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; #undef PROC } } template void dilate2D_0h_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *q1, *q2, a, c; ptrdiff_t numint, i, j; INIT if (numint == 1) { p2= input; q2= output; for (j= 0; j < height; j++) { a= *p2 & c; a|= a << 1; *q2= a; p2+= numint; q2+= numint; } } else if (numint > 1) { p1= input; q1= output; for (i=1 ; i < numint ; i++) { p3= p1 + 1; p2= p1; q2= q1; for (j= 0; j < height; j++) { a= *p2; a|= ((*p3 & LB) != 0)?(RB | (a << 1)):( a << 1); *q2= a; q2+= numint; p2+= numint; p3+= numint; } p1++; q1++; } p2= p1; q2= q1; for (j= 0; j < height; j++) { a= *p2 & c; a|= (a << 1); *q2= a; q2+= numint; p2+= numint; } } } template void dilate2D_0v_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *q1, *q2, a, b, c; ptrdiff_t numint, i, j; INIT if (numint == 1) { p2= input; q2= output; a= *p2 & c; for (j= 1; j < height; j++) { p2+= numint; b= a; a= *p2 & c; *q2= a | b; q2+= numint; } *q2= a; } else if (numint > 1) { p1= input; q1= output; for (i=1 ; i < numint ; i++) { p2= p1; q2= q1; a= *p2; for (j= 1; j < height; j++) { p2+= numint; b= a; a= *p2; *q2= a | b; q2+= numint; } *q2= a; p1++; q1++; } p2= p1; q2= q1; a= *p2 & c; for (j= 1; j < height; j++) { p2+= numint; b= a; a= *p2 & c; *q2= a | b; q2+= numint; } *q2= a; } } template void dilate2D_4_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *p4, *q1, *q2, a, b, c, d, e; ptrdiff_t numint, i, j; INIT if (numint == 1) { p2= input; q2= output; a= *p2 & c; #define PROC(x) \ e= x | (x >> 1) | (x << 1); PROC(a) p2+= numint; b= *p2 & c; *q2= e | b; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; d= *p2 & c; PROC(b) *q2= a | e | d; a= b; b= d; } PROC(b) q2+= numint; *q2= a | e; #undef PROC } else if (numint > 1) { p1= input; q1= output; p2= p1; q2= q1; p4= p1 + 1; a= *p2; #define PROC(x) \ e= (*p4 & LB)?(x | (x >> 1) | (RB | (x << 1))) \ :(x | (x >> 1) | (x << 1)); PROC(a); p2+= numint; p4+= numint; b= *p2; *q2= e | b; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; d= *p2; PROC(b) *q2= a | e | d; a= b; b= d; p4+= numint; } PROC(b) q2+= numint; *q2= a | e; #undef PROC for (i= 1; i < (numint - 1); i++) { p3= p1; p1++; q1++; p2= p1; q2= q1; p4= p1 + 1; a= *p2; #define PROC(x) \ e= ((*p4 & LB) != 0)? \ ((*p3 & RB) != 0)?(x | (LB | (x >> 1)) | (RB | (x << 1))) \ :(x | (x >> 1) | (RB | (x << 1))) \ : \ ((*p3 & RB) != 0)?(x | (LB | (x >> 1)) | (x << 1)) \ :(x | (x >> 1) | (x << 1)); PROC(a) p2+= numint; p3+= numint; p4+= numint; b= *p2; *q2= e | b; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; d= *p2; PROC(b) *q2= a | e | d; a= b; b= d; p3+= numint; p4+= numint; } PROC(b); q2+= numint; *q2= a | e; #undef PROC } p3= p1; p1++; q1++; p2= p1; q2= q1; a= *p2 & c; #define PROC(x) \ e= ((*p3 & RB) != 0)?(x | (LB | (x >> 1)) | (x << 1)) \ :(x | (x >> 1) | (x << 1)); PROC(a) p2+= numint; p3+= numint; b= *p2 & c; *q2= e | b; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; d= *p2 & c; PROC(b) *q2= a | e | d; a= b; b= d; p3+= numint; } PROC(b) q2+= numint; *q2= a | e; #undef PROC } } template void dilate2D_8_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *p4, *q1, *q2, a, b, c, d; ptrdiff_t numint, i, j; INIT if (numint == 1) { p2= input; q2= output; #define PROC(x) \ x= *p2 & c; \ x&= (x >> 1) | (x << 1); PROC(a) p2+= numint; PROC(b) *q2= a | b; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; PROC(d) *q2= a | b | d; a= b; b= d; } q2+= numint; *q2= a | b; #undef PROC } else if (numint > 1) { p1= input; q1= output; p2= p1; q2= q1; p4= p1 + 1; #define PROC(x) \ x= *p2; \ x|= (*p4 & LB)?((x >> 1)|(RB | (x << 1))) \ :((x >> 1)|(x << 1)); PROC(a) p2+= numint; p4+= numint; PROC(b) *q2= a | b; for (j= 2; j < height; j++) { p2+= numint; p4+= numint; q2+= numint; PROC(d); *q2= a | b | d; a= b; b= d; } q2+= numint; *q2= a | b; #undef PROC for (i= 1; i < (numint - 1); i++) { p3= p1; p1++; q1++; p2= p1; q2= q1; p4= p1 + 1; #define PROC(x) \ x= *p2; \ x|= ((*p4 & LB) != 0)? \ ((*p3 & RB) != 0)?((LB | (x >> 1)) | (RB | (x << 1))) \ :((x >> 1) | (RB | (x << 1))) \ : \ ((*p3 & RB) != 0)?((LB | (x >> 1)) | (x << 1)) \ :((x >> 1) | (x << 1)); PROC(a) p2+= numint; p3+= numint; p4+= numint; PROC(b) *q2= a | b; for (j= 2; j < height; j++) { p2+= numint; p3+= numint; p4+= numint; q2+= numint; PROC(d) *q2= a | b | d; a= b; b= d; } q2+= numint; *q2= a | b; #undef PROC } p3= p1; p1++; q1++; p2= p1; q2= q1; #define PROC(x) \ x= *p2 & c; \ x|= ((*p3 & RB) != 0)?((LB | (x >> 1)) | (x << 1)) \ :((x >> 1) | (x << 1)); PROC(a) p2+= numint; p3+= numint; PROC(b) *q2= a | b; for (j= 2; j < height; j++) { p2+= numint; p3+= numint; q2+= numint; PROC(d) *q2= a | b | d; a= b; b= d; } q2+= numint; *q2= a | b; #undef PROC } } template void erode2D_0_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *q1, *q2, a, b, c; ptrdiff_t numint, i, j; INIT; if (numint == 1) { p2= input; q2= output; #define PROC(x) \ x= *p2 & c; \ x&= x >> 1; PROC(a) *q2= 0; for (j= 1; j < height; j++) { p2+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } #undef PROC } else if (numint > 1) { p1= input; q1= output; p2= p1; q2= q1; #define PROC(x) \ x= *p2; \ x&= x >> 1; PROC(a); *q2= 0; for (j= 1; j < height; j++) { p2+= numint; q2+= numint; b= a; PROC(a); *q2= a & b; #undef PROC } for (i=2 ; i < numint; i++) { p3= p1; p1++; q1++; p2= p1; q2= q1; #define PROC(x) \ x= *p2; \ x&= ((*p3 & RB) != 0)?(LB | (x >> 1)):( x>> 1); PROC(a); *q2= 0; for (j= 1; j < height; j++) { p2+= numint; p3+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; #undef PROC } } p3= p1; p1++; q1++; p2= p1; q2= q1; #define PROC(x) \ x= *p2 & c; \ x&= ((*p3 & RB) != 0)?(LB | (x >> 1)):(x >> 1); PROC(a) *q2= 0; for (j= 1; j < height; j++) { p2+= numint; p3+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; #undef PROC } } } template void erode2D_1_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *q1, *q2, a, b, c; ptrdiff_t numint, i, j; INIT if (numint == 1) { p2= input; q2= output; #define PROC(x) \ x= *p2 & c; \ x&= x << 1; PROC(a) for (j= 1; j < height; j++) { p2+= numint; b= a; PROC(a) *q2= a & b; q2+= numint; } *q2= a; #undef PROC } else if (numint > 1) { p1= input; q1= output; for (i=1 ; i < numint ; i++) { p3= p1 + 1; p2= p1; q2= q1; #define PROC(x) \ x= *p2; \ x&= ((*p3 & LB) != 0)?(RB | (x << 1)):( x << 1); PROC(a) for (j= 1; j < height; j++) { p2+= numint; p3+= numint; b= a; PROC(a) *q2= a & b; q2+= numint; } #undef PROC *q2= a; p1++; q1++; } p2= p1; q2= q1; #define PROC(x) \ x= *p2 & c; \ x&= ( x << 1); PROC(a) for (j= 1; j < height; j++) { p2+= numint; b= a; PROC(a) *q2= a & b; q2+= numint; } *q2= a; #undef PROC } } template void erode2D_0h_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *q1, *q2, a, c; ptrdiff_t numint, i, j; INIT; if (numint == 1) { p2= input; q2= output; for (j= 0; j < height; j++) { a= *p2 & c; a&= a >> 1; *q2= a; p2+= numint; q2+= numint; } } else if (numint > 1) { p1= input; q1= output; p2= p1; q2= q1; for (j= 0; j < height; j++) { a= *p2; a&= a >> 1; *q2= a; p2+= numint; q2+= numint; } for (i=2 ; i < numint; i++) { p3= p1; p1++; q1++; p2= p1; q2= q1; for (j= 0; j < height; j++) { a= *p2; a&= ((*p3 & RB) != 0)?(LB | (a >> 1)):(a >> 1); *q2= a; p2+= numint; p3+= numint; q2+= numint; } } p3= p1; p1++; q1++; p2= p1; q2= q1; for (j= 0; j < height; j++) { a= *p2 & c; a&= ((*p3 & RB) != 0)?(LB | (a >> 1)):(a >> 1); *q2= a; p2+= numint; p3+= numint; q2+= numint; } } } template void erode2D_0v_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *q1, *q2, a, b, c; ptrdiff_t numint, i, j; INIT; if (numint == 1) { p2= input; q2= output; a= *p2 & c; *q2= 0; for (j= 1; j < height; j++) { p2+= numint; q2+= numint; b= a; a= *p2 & c; *q2= a & b; } } else if (numint > 1) { p1= input; q1= output; p2= p1; q2= q1; a= *p2; *q2= 0; for (j= 1; j < height; j++) { p2+= numint; q2+= numint; b= a; a= *p2; *q2= a & b; } for (i=2 ; i < numint; i++) { p3= p1; p1++; q1++; p2= p1; q2= q1; a= *p2; *q2= 0; for (j= 1; j < height; j++) { p2+= numint; p3+= numint; q2+= numint; b= a; a= *p2; *q2= a & b; } } p3= p1; p1++; q1++; p2= p1; q2= q1; a= *p2 & c; *q2= 0; for (j= 1; j < height; j++) { p2+= numint; p3+= numint; q2+= numint; b= a; a= *p2 & c; *q2= a & b; } } } template void erode2D_4_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *p4, *q1, *q2, a, b, c, d, e; ptrdiff_t numint, i, j; INIT if (numint == 1) { p2= input; q2= output; a= *p2 & c; p2+= numint; b= *p2 & c; *q2= 0; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; d= *p2 & c; e= b & (b >> 1) & (b << 1); *q2= a & e & d; a= b; b= d; } q2+= numint; *q2= 0; } else if (numint > 1) { p1= input; q1= output; p2= p1; q2= q1; p4= p1 + 1; a= *p2; p2+= numint; p4+= numint; b= *p2; *q2= 0; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; d= *p2; e= ((*p4 & LB) != 0)?(b & (b >> 1) & (RB | (b << 1))) :(b & (b >> 1) & (b << 1)); *q2= a & e & d; a= b; b= d; p4+= numint; } q2+= numint; *q2= 0; for (i= 1; i < (numint - 1); i++) { p3= p1; p1++; q1++; p2= p1; q2= q1; p4= p1 + 1; a= *p2; p2+= numint; p3+= numint; p4+= numint; b= *p2; *q2= 0; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; d= *p2; e= ((*p4 & LB) != 0)? ((*p3 & RB) != 0)?(b & (LB | (b >> 1)) & (RB | (b << 1))) :(b & (b >> 1) & (RB | (b << 1))) : ((*p3 & RB) != 0)?(b & (LB | (b >> 1)) & (b << 1)) :(b & (b >> 1) & (b << 1)); *q2= a & e & d; a= b; b= d; p3+= numint; p4+= numint; } q2+= numint; *q2= 0; } p3= p1; p1++; q1++; p2= p1; q2= q1; a= *p2 & c; p2+= numint; p3+= numint; b= *p2 & c; *q2= 0; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; d= *p2 & c; e= ((*p3 & RB) != 0)?(b & (LB | (b >> 1)) & (b << 1)) :(b & (b >> 1) & (b << 1)); *q2= a & e & d; a= b; b= d; p3+= numint; } q2+= numint; *q2= 0; } } template void erode2D_8_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *p4, *q1, *q2, a, b, c, d; ptrdiff_t numint, i, j; INIT if (numint == 1) { p2= input; q2= output; #define PROC(x) \ x= *p2 & c; \ x&= (x >> 1) & (x << 1); PROC(a) p2+= numint; PROC(b) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; PROC(d) *q2= a & b & d; a= b; b= d; #undef PROC } q2+= numint; *q2= 0; } else if (numint > 1) { p1= input; q1= output; p2= p1; q2= q1; p4= p1 + 1; #define PROC(x) \ x= *p2; \ x&= (*p4 & LB)?((x >> 1)&(RB | (x << 1))) \ :((x >> 1)&(x << 1)); PROC(a) p2+= numint; p4+= numint; PROC(b) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p4+= numint; q2+= numint; PROC(d); *q2= a & b & d; a= b; b= d; #undef PROC } q2+= numint; *q2= 0; for (i= 1; i < (numint - 1); i++) { p3= p1; p1++; q1++; p2= p1; q2= q1; p4= p1 + 1; #define PROC(x) \ x= *p2; \ x&= ((*p4 & LB) != 0)? \ ((*p3 & RB) != 0)?((LB | (x >> 1)) & (RB | (x << 1))) \ :((x >> 1) & (RB | (x << 1))) \ : \ ((*p3 & RB) != 0)?((LB | (x >> 1)) & (x << 1)) \ :((x >> 1) & (x << 1)); PROC(a) p2+= numint; p3+= numint; p4+= numint; PROC(b) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p3+= numint; p4+= numint; q2+= numint; PROC(d) *q2= a & b & d; a= b; b= d; } q2+= numint; *q2= 0; #undef PROC } p3= p1; p1++; q1++; p2= p1; q2= q1; #define PROC(x) \ x= *p2 & c; \ x&= ((*p3 & RB) != 0)?((LB | (x >> 1)) & (x << 1)) \ :((x >> 1) & (x << 1)); PROC(a) p2+= numint; p3+= numint; PROC(b) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p3+= numint; q2+= numint; PROC(d) *q2= a & b & d; a= b; b= d; #undef PROC } q2+= numint; *q2= 0; } } #undef INIT #define INIT \ numint= (width + Numb - 1) / Numb; \ numg= numint * height; \ c= ((width % Numb) == 0)?(AB):(AB << (Numb - (width % Numb))); template void erode3D_0_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *p5, *p6, *q1, *q2, a, b, c; ptrdiff_t numint, i, j, k, numg; INIT if (numint == 1) { p2= input; p5= p2 + numg; q2= output; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5 & c; \ x&= x >> 1; for (k= 1; k < depth; k++){ PROC(a) *q2= 0; for (j= 1; j < height; j++) { p2+= numint; p5+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; p5+= numint; q2+= numint; } #undef PROC } else if (numint > 1) { p1= input; q1= output; p2= p1; p5= p2 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5; \ x&= x >> 1; for (k= 1; k < depth; k++) { PROC(a); *q2= 0; for (j = 1; j < height; j++) { p2+= numint; p5+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; p5+= numint; q2+= numint; } #undef PROC for (i=2 ; i < numint; i++) { p3= p1; p6= p3 + numg; p1++; q1++; p2= p1; p5= p2 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5; \ x&= ((*p3 & *p6 & RB) != 0)?(LB | (x >> 1)):( x>> 1); for (k= 1; k < depth; k++) { PROC(a); *q2= 0; for (j= 1; j < height; j++) { p2+= numint; p3+= numint; p5+= numint; p6+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; p3+= numint; p5+= numint; p6+= numint; q2+= numint; } #undef PROC } p3= p1; p6= p3 + numg; p1++; q1++; p2= p1; p5= p2 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5 & c; \ x&= ((*p3 & *p6 & RB) != 0)?(LB | (x >> 1)):( x>> 1); for (k= 1; k < depth; k++){ PROC(a); *q2= 0; for (j= 1; j < height; j++) { p2+= numint; p3+= numint; p5+= numint; p6+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; p3+= numint; p5+= numint; p6+= numint; q2+= numint; } #undef PROC } } template void erode3D_1_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *p5, *p6, *q1, *q2, a, b, c; ptrdiff_t numint, numg, i, j, k; INIT if (numint == 1) { p2= input; p5= p2 + numg; q2= output; #define PROC(x) \ x= (*p2 & *p5) & c; \ x&= x << 1; for (k= 1; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; p5+= numint; b= a; PROC(a) *q2= a & b; q2+= numint; } *q2= a; p2+= numint; p5+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } #undef PROC } else if (numint > 1) { p1= input; q1= output; for (i=1 ; i < numint; i++) { p3= p1 + 1; p6= p3 + numg; p2= p1; p5= p2 + numg; q2= q1; #define PROC(x) \ x= *p2 & *p5; \ x&= (((*p3 & *p6) & LB) != 0)?(RB | (x << 1)):( x << 1); for (k= 1; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; p5+= numint; p3+= numint; p6+= numint; b= a; PROC(a) *q2= a & b; q2+= numint; } *q2= a; p2+= numint; p5+= numint; p3+= numint; p6+= numint; q2+= numint; } #undef PROC for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } p1++; q1++; } p2= p1; p5= p2 + numg; q2= q1; #define PROC(x) \ x= (*p2 & *p5) & c; \ x&= x << 1; for (k= 1; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; p5+= numint; b= a; PROC(a) *q2= a & b; q2+= numint; } *q2= a; p2+= numint; p5+= numint; q2+= numint; } #undef PROC for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } } } template void erode3D_0hv_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *q1, *q2, a, b, c; ptrdiff_t numint, i, j, k, numg; INIT if (numint == 1) { p2= input; q2= output; #define PROC(x) \ x= *p2 & c; \ x&= x >> 1; for (k= 0; k < depth; k++){ PROC(a) *q2= 0; for (j= 1; j < height; j++) { p2+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; q2+= numint; } #undef PROC } else if (numint > 1) { p1= input; q1= output; p2= p1; q2= q1; #define PROC(x) \ x= *p2; \ x&= x >> 1; for (k= 0; k < depth; k++) { PROC(a); *q2= 0; for (j = 1; j < height; j++) { p2+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } #undef PROC p2+= numint; q2+= numint; } for (i= 2; i < numint; i++) { p3= p1; p1++; q1++; p2= p1; q2= q1; #define PROC(x) \ x= *p2; \ x&= ((*p3 & RB) != 0)?(LB | (x >> 1)):( x>> 1); for (k= 0; k < depth; k++) { PROC(a); *q2= 0; for (j= 1; j < height; j++) { p2+= numint; p3+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; p3+= numint; q2+= numint; } #undef PROC } p3= p1; p1++; q1++; p2= p1; q2= q1; #define PROC(x) \ x= *p2 & c; \ x&= ((*p3 & RB) != 0)?(LB | (x >> 1)):( x>> 1); for (k= 0; k < depth; k++){ PROC(a); *q2= 0; for (j= 1; j < height; j++) { p2+= numint; p3+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; p3+= numint; q2+= numint; } #undef PROC } } template void erode3D_0ha_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *p5, *p6, *q1, *q2, a, c; ptrdiff_t numint, i, j, k, numg; INIT if (numint == 1) { p2= input; p5= p2 + numg; q2= output; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5 & c; \ x&= x >> 1; for (k= 1; k < depth; k++){ for (j= 0; j < height; j++) { PROC(a) *q2= a; p2+= numint; p5+= numint; q2+= numint; } } #undef PROC } else if (numint > 1) { p1= input; q1= output; p2= p1; p5= p2 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5; \ x&= x >> 1; for (k= 1; k < depth; k++) { for (j= 0; j < height; j++) { PROC(a) *q2= a; p2+= numint; p5+= numint; q2+= numint; } #undef PROC } for (i= 2; i < numint; i++) { p3= p1; p6= p3 + numg; p1++; q1++; p2= p1; p5= p2 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5; \ x&= ((*p3 & *p6 & RB) != 0)?(LB | (x >> 1)):( x>> 1); for (k= 1; k < depth; k++) { for (j= 0; j < height; j++) { PROC(a) *q2= a; p2+= numint; p3+= numint; p5+= numint; p6+= numint; q2+= numint; } } #undef PROC } p3= p1; p6= p3 + numg; p1++; q1++; p2= p1; p5= p2 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5 & c; \ x&= ((*p3 & *p6 & RB) != 0)?(LB | (x >> 1)):( x>> 1); for (k= 1; k < depth; k++){ for (j= 0; j < height; j++) { PROC(a) *q2= a; p2+= numint; p3+= numint; p5+= numint; p6+= numint; q2+= numint; } } #undef PROC } } template void erode3D_0va_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p5, *q1, *q2, a, b, c; ptrdiff_t numint, i, j, k, numg; INIT if (numint == 1) { p2= input; p5= p2 + numg; q2= output; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5 & c; for (k= 1; k < depth; k++){ PROC(a) *q2= 0; for (j= 1; j < height; j++) { p2+= numint; p5+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; p5+= numint; q2+= numint; } #undef PROC } else if (numint > 1) { p1= input; q1= output; for (i= 1; i < numint; i++) { p2= p1; p5= p2 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5; for (k= 1; k < depth; k++) { PROC(a); *q2= 0; for (j= 1; j < height; j++) { p2+= numint; p5+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; p5+= numint; q2+= numint; } #undef PROC p1++; q1++; } p2= p1; p5= p2 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5 & c; for (k= 1; k < depth; k++){ PROC(a); *q2= 0; for (j= 1; j < height; j++) { p2+= numint; p5+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; p5+= numint; q2+= numint; } #undef PROC } } template void erode3D_0v_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *q1, *q2, a, b, c; ptrdiff_t numint, i, j, k, numg; INIT if (numint == 1) { p2= input; q2= output; #define PROC(x) \ x= *p2 & c; for (k= 0; k < depth; k++){ PROC(a) *q2= 0; for (j= 1; j < height; j++) { p2+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; q2+= numint; } #undef PROC } else if (numint > 1) { p1= input; q1= output; for (i= 1; i < numint; i++) { p2= p1; q2= q1; #define PROC(x) \ x= *p2; for (k= 0; k < depth; k++) { PROC(a); *q2= 0; for (j= 1; j < height; j++) { p2+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; q2+= numint; } #undef PROC p1++; q1++; } p2= p1; q2= q1; #define PROC(x) \ x= *p2 & c; for (k= 0; k < depth; k++){ PROC(a); *q2= 0; for (j= 1; j < height; j++) { p2+= numint; q2+= numint; b= a; PROC(a) *q2= a & b; } p2+= numint; q2+= numint; } #undef PROC } } template void erode3D_0a_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p5, *q1, *q2, a, c; ptrdiff_t numint, i, j, k, numg; INIT if (numint == 1) { p2= input; p5= p2 + numg; q2= output; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5 & c; for (k= 1; k < depth; k++){ for (j= 0; j < height; j++) { PROC(a) *q2= a; p2+= numint; p5+= numint; q2+= numint; } } #undef PROC } else if (numint > 1) { p1= input; q1= output; for (i= 1; i < numint; i++) { p2= p1; p5= p2 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5; for (k= 1; k < depth; k++) { for (j= 0; j < height; j++) { PROC(a) *q2= a; p2+= numint; p5+= numint; q2+= numint; } } #undef PROC p1++; q1++; } p2= p1; p5= p2 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x) \ x= *p2 & *p5 & c; for (k= 1; k < depth; k++){ for (j= 0; j < height; j++) { PROC(a) *q2= a; p2+= numint; p5+= numint; q2+= numint; } } #undef PROC } } template void erode3D_18_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *q1, *q2; size_t c, a1, b1, d1, a2, b2, d2, e, f, g; ptrdiff_t numint, i, j, k, numg; INIT if (numint == 1) { p2= input; p5= p2 + numg; p8= p5 + numg; q2= output; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC \ d1= *p5 & c; \ d1&= (d1 << 1) & (d1 >> 1); \ d2= *p2 & *p8 & c; for (k= 2; k < depth; k++){ PROC a1= d1; a2= d2; p2+= numint; p5+= numint; p8+= numint; PROC b1= d1; b2= d2; *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; q2+= numint; PROC *q2= a1 & b1 & d1 & a2 & b2 & (b2 << 1) & (b2 >> 1) & d2; a1= b1; b1= d1; a2= b2; b2= d2; } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; q2+= numint; } #undef PROC for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } else if (numint > 1) { p1= input; q1= output; p2= p1; p5= p2 + numg; p8= p5 + numg; p4= p2 + 1; p7= p5 + 1; p10= p8 + 1; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC \ d1= *p5; \ d1&= ((*p7 & LB) != 0)?((RB | (d1 << 1)) & (d1 >> 1)) \ :((d1 << 1) & (d1 >> 1)); \ d2= *p2 & *p8; for (k= 2; k < depth; k++){ PROC a1= d1; a2= d2; p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; PROC b1= d1; b2= d2; *q2= 0; for (j= 2; j < height; j++) { e= *p4 & *p10; p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; PROC g= a1 & b1 & d1 & a2 & b2 & d2; *q2= ((e & LB) != 0)?(g & (RB | (b2 << 1)) & (b2 >> 1)) :(g & (b2 << 1) & (b2 >> 1)); a1= b1; b1= d1; a2= b2; b2= d2; } #undef PROC q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } for (i=2 ; i < numint; i++) { p3= p1; p6= p3 + numg; p9= p6 + numg; p1++; q1++; p2= p1; p5= p2 + numg; p8= p5 + numg; p4= p2 + 1; p7= p5 + 1; p10= p8 + 1; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC \ d1= *p5; \ d1&= ((*p6 & RB) != 0)? \ ((*p7 & LB) != 0)?((RB | (d1 << 1)) & (LB | (d1 >> 1))) \ :((d1 << 1) & (LB | (d1 >> 1))) \ : \ ((*p7 & LB) != 0)?((RB | (d1 << 1)) & (d1 >> 1)) \ :((d1 << 1) & (d1 >> 1)); \ d2= *p2 & *p8; for (k= 2; k < depth; k++){ PROC a1= d1; a2= d2; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; PROC b1= d1; b2= d2; *q2= 0; for (j= 2; j < height; j++) { e= *p4 & *p10; f= *p3 & *p9; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; PROC g= a1 & b1 & d1 & a2 & b2 & d2; *q2= ((f & RB) != 0)? ((e & LB) != 0)?(g & (RB | (b2 << 1)) & (LB | (b2 >> 1))) :(g & (b2 << 1) & (LB | (b2 >> 1))) : ((e & LB) != 0)?(g & (RB | (b2 << 1)) & (b2 >> 1)) :(g & (b2 << 1) & (b2 >> 1)); a1= b1; b1= d1; a2= b2; b2= d2; } #undef PROC q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } p3= p1; p6= p3 + numg; p9= p6 + numg; p1++; q1++; p2= p1; p5= p2 + numg; p8= p5 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC \ d1= *p5; \ d1&= ((*p6 & RB) != 0)?((d1 << 1) & (LB | (d1 >> 1))) \ :((d1 << 1) & (d1 >> 1)); \ d2= *p2 & *p8; for (k= 2; k < depth; k++){ PROC a1= d1; a2= d2; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; PROC b1= d1; b2= d2; *q2= 0; for (j= 2; j < height; j++) { f= *p3 & *p9; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; q2+= numint; PROC g= a1 & b1 & d1 & a2 & b2 & d2; *q2= ((f & RB) != 0)?(g & (b2 << 1) & (LB | (b2 >> 1))) :(g & (b2 << 1) & (b2 >> 1)); a1= b1; b1= d1; a2= b2; b2= d2; } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; q2+= numint; } #undef PROC for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } } template void erode3D_10_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *q1, *q2; size_t c, a1, b1, d1, b2, d2; ptrdiff_t numint, i, j, k, numg; INIT if (numint == 1) { p2= input; p5= p2 + numg; p8= p5 + numg; q2= output; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC \ d1= *p5 & c; \ d1&= (d1 << 1) & (d1 >> 1); \ d2= *p2 & *p8 & c; for (k= 2; k < depth; k++){ PROC a1= d1; p2+= numint; p5+= numint; p8+= numint; PROC b1= d1; b2= d2; *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; q2+= numint; PROC *q2= a1 & b1 & d1 & b2; a1= b1; b1= d1; b2= d2; } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; q2+= numint; } #undef PROC for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } else if (numint > 1) { p1= input; q1= output; p2= p1; p5= p2 + numg; p8= p5 + numg; p4= p2 + 1; p7= p5 + 1; p10= p8 + 1; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC \ d1= *p5; \ d1&= ((*p7 & LB) != 0)?((RB | (d1 << 1)) & (d1 >> 1)) \ :((d1 << 1) & (d1 >> 1)); \ d2= *p2 & *p8; for (k= 2; k < depth; k++){ PROC a1= d1; p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; PROC b1= d1; b2= d2; *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; PROC *q2= a1 & b1 & d1 & b2; a1= b1; b1= d1; b2= d2; } #undef PROC q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } for (i=2 ; i < numint; i++) { p3= p1; p6= p3 + numg; p9= p6 + numg; p1++; q1++; p2= p1; p5= p2 + numg; p8= p5 + numg; p4= p2 + 1; p7= p5 + 1; p10= p8 + 1; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC \ d1= *p5; \ d1&= ((*p6 & RB) != 0)? \ ((*p7 & LB) != 0)?((RB | (d1 << 1)) & (LB | (d1 >> 1))) \ :((d1 << 1) & (LB | (d1 >> 1))) \ : \ ((*p7 & LB) != 0)?((RB | (d1 << 1)) & (d1 >> 1)) \ :((d1 << 1) & (d1 >> 1)); \ d2= *p2 & *p8; for (k= 2; k < depth; k++){ PROC a1= d1; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; PROC b1= d1; b2= d2; *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; PROC *q2= a1 & b1 & d1 & b2; a1= b1; b1= d1; b2= d2; } #undef PROC q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } p3= p1; p6= p3 + numg; p9= p6 + numg; p1++; q1++; p2= p1; p5= p2 + numg; p8= p5 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC \ d1= *p5; \ d1&= ((*p6 & RB) != 0)?((d1 << 1) & (LB | (d1 >> 1))) \ :((d1 << 1) & (d1 >> 1)); \ d2= *p2 & *p8; for (k= 2; k < depth; k++){ PROC a1= d1; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; PROC b1= d1; b2= d2; *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; q2+= numint; PROC *q2= a1 & b1 & d1 & b2; a1= b1; b1= d1; b2= d2; } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; q2+= numint; } #undef PROC for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } } template void erode3D_a_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p5, *p8, *q1, *q2; size_t c; ptrdiff_t numint, i, j, k, numg; INIT p1= input; q1= output; for (i= 1 ; i < numint; i++) { p2= p1; p5= p2; p8= p5 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= *p5 & *p8; q2+= numint; p5+= numint; p8+= numint; } for (k= 2; k < depth; k++){ for (j= 0; j < height; j++) { *q2= *p2 & *p5 & *p8; q2+= numint; p2+= numint; p5+= numint; p8+= numint; } } for (j= 0; j < height; j++) { *q2= *p2 & *p5; q2+= numint; p2+= numint; p5+= numint; } p1++; q1++; } p2= p1; p5= p2; q2= q1; p8= p5 + numg; for (j= 0; j < height; j++) { *q2= *p5 & *p8 & c; q2+= numint; p5+= numint; p8+= numint; } for (k= 2; k < depth; k++) for (j= 0; j < height; j++) { *q2= *p2 & *p5 & *p8 & c; q2+= numint; p2+= numint; p5+= numint; p8+= numint; } for (j= 2; j < height; j++) { *q2= *p2 & *p5 & c; q2+= numint; p2+= numint; p5+= numint; } } template void dilate3D_0_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *p5, *p6, *q1, *q2, a, b, c; ptrdiff_t numint, numg, i, j, k; INIT if (numint == 1) { p2= input; p5= p2 + numg; q2= output; #define PROC(x) \ x= (*p2 | *p5) & c; \ x|= x << 1; for (k= 1; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; p5+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; p2+= numint; p5+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } #undef PROC } else if (numint > 1) { p1= input; q1= output; for (i=1 ; i < numint; i++) { p3= p1 + 1; p6= p3 + numg; p2= p1; p5= p2 + numg; q2= q1; #define PROC(x) \ x= *p2 | *p5; \ x|= (((*p3 | *p6) & LB) != 0)?(RB | (x << 1)):( x << 1); for (k= 1; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; p5+= numint; p3+= numint; p6+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; p2+= numint; p5+= numint; p3+= numint; p6+= numint; q2+= numint; } #undef PROC for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } p1++; q1++; } p2= p1; p5= p2 + numg; q2= q1; #define PROC(x) \ x= (*p2 | *p5) & c; \ x|= x << 1; for (k= 1; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; p5+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; p2+= numint; p5+= numint; q2+= numint; } #undef PROC for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } } } template void dilate3D_0hv_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *q1, *q2, a, b, c; ptrdiff_t numint, numg, i, j, k; INIT if (numint == 1) { p2= input; q2= output; #define PROC(x) \ x= *p2 & c; \ x|= x << 1; for (k= 0; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; p2+= numint; q2+= numint; } #undef PROC } else if (numint > 1) { p1= input; q1= output; for (i=1 ; i < numint; i++) { p3= p1 + 1; p2= p1; q2= q1; #define PROC(x) \ x= *p2; \ x|= ((*p3 & LB) != 0)?(RB | (x << 1)):( x << 1); for (k= 0; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; p3+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; p2+= numint; p3+= numint; q2+= numint; } #undef PROC p1++; q1++; } p2= p1; q2= q1; #define PROC(x) \ x= *p2 & c; \ x|= x << 1; for (k= 0; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; p2+= numint; q2+= numint; } #undef PROC } } template void dilate3D_0ha_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *p5, *p6, *q1, *q2, a, c; ptrdiff_t numint, numg, i, j, k; INIT if (numint == 1) { p2= input; p5= p2 + numg; q2= output; #define PROC(x) \ x= (*p2 | *p5) & c; \ x|= x << 1; for (k= 1; k < depth; k++){ for (j= 0; j < height; j++) { PROC(a) *q2= a; p2+= numint; p5+= numint; q2+= numint; } } for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } #undef PROC } else if (numint > 1) { p1= input; q1= output; for (i=1 ; i < numint; i++) { p3= p1 + 1; p6= p3 + numg; p2= p1; p5= p2 + numg; q2= q1; #define PROC(x) \ x= *p2 | *p5; \ x|= (((*p3 | *p6) & LB) != 0)?(RB | (x << 1)):( x << 1); for (k= 1; k < depth; k++){ for (j= 0; j < height; j++) { PROC(a) *q2= a; p2+= numint; p5+= numint; p3+= numint; p6+= numint; q2+= numint; } } #undef PROC for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } p1++; q1++; } p2= p1; p5= p2 + numg; q2= q1; #define PROC(x) \ x= (*p2 | *p5) & c; \ x|= x << 1; for (k= 1; k < depth; k++){ for (j= 0; j < height; j++) { PROC(a) *q2= a; p2+= numint; p5+= numint; q2+= numint; } } #undef PROC for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } } } template void dilate3D_0va_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p5, *q1, *q2, a, b, c; ptrdiff_t numint, numg, i, j, k; INIT if (numint == 1) { p2= input; p5= p2 + numg; q2= output; #define PROC(x) \ x= (*p2 | *p5) & c; for (k= 1; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; p5+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; p2+= numint; p5+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } #undef PROC } else if (numint > 1) { p1= input; q1= output; for (i=1 ; i < numint; i++) { p2= p1; p5= p2 + numg; q2= q1; #define PROC(x) \ x= *p2 | *p5; for (k= 1; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; p5+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; p2+= numint; p5+= numint; q2+= numint; } #undef PROC for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } p1++; q1++; } p2= p1; p5= p2 + numg; q2= q1; #define PROC(x) \ x= (*p2 | *p5) & c; for (k= 1; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; p5+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; p2+= numint; p5+= numint; q2+= numint; } #undef PROC for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } } } template void dilate3D_0v_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *q1, *q2, a, b, c; ptrdiff_t numint, numg, i, j, k; INIT if (numint == 1) { p2= input; q2= output; #define PROC(x) \ x= *p2 & c; for (k= 0; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; p2+= numint; q2+= numint; } #undef PROC } else if (numint > 1) { p1= input; q1= output; for (i=1 ; i < numint; i++) { p2= p1; q2= q1; #define PROC(x) \ x= *p2; for (k= 0; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; p2+= numint; q2+= numint; } #undef PROC p1++; q1++; } p2= p1; q2= q1; #define PROC(x) \ x= *p2 & c; for (k= 0; k < depth; k++){ PROC(a) for (j= 1; j < height; j++) { p2+= numint; b= a; PROC(a) *q2= a | b; q2+= numint; } *q2= a; p2+= numint; q2+= numint; } #undef PROC } } template void dilate3D_0a_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p5, *q1, *q2, c; ptrdiff_t numint, numg, i, j, k; INIT if (numint == 1) { p2= input; p5= p2 + numg; q2= output; for (k= 1; k < depth; k++){ for (j= 0; j < height; j++) { *q2= (*p2 | *p5) & c; p2+= numint; p5+= numint; q2+= numint; } } for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } } else if (numint > 1) { p1= input; q1= output; for (i=1 ; i < numint; i++) { p2= p1; p5= p2 + numg; q2= q1; for (k= 1; k < depth; k++){ for (j= 0; j < height; j++) { *q2= *p2 | *p5; p2+= numint; p5+= numint; q2+= numint; } } #undef PROC for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } p1++; q1++; } p2= p1; p5= p2 + numg; q2= q1; for (k= 1; k < depth; k++){ for (j= 0; j < height; j++) { *q2= (*p2 | *p5) & c; p2+= numint; p5+= numint; q2+= numint; } } for (j= 0; j < height; j++) { *q2= *p2; p2+= numint; q2+= numint; } } } template void dilate3D_18_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *q1, *q2; size_t c, a1, b1, d1, a2, b2, d2, e, f, g; ptrdiff_t numint, i, j, k, numg; INIT if (numint == 1) { p2= input; p5= p2; p8= p5 + numg; q2= output; #define PROC \ d1= *p5 & c; \ d1|= ((d1 << 1) | (d1 >> 1)) & c; #define PROD \ *q2= a1 | b1 | d1 | a2 | b2 | (b2 << 1) | (b2 >> 1) | d2; \ q2+= numint; PROC d2= *p8 & c; a1= 0; b1= d1; a2= 0; b2= d2; p5+= numint; p8+= numint; PROC d2= *p8 & c; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { p5+= numint; p8+= numint; PROC d2= *p8 & c; PROD a1= b1; b1= d1; a2= b2; b2= d2; } PROD p5+= numint; p8+= numint; for (k= 2; k < depth; k++){ PROC d2= (*p2 | *p8) & c; a1= 0; b1= d1; a2= 0; b2= d2; p2+= numint; p5+= numint; p8+= numint; PROC d2= (*p2 | *p8) & c; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; PROC d2= (*p2 | *p8) & c; PROD a1= b1; b1= d1; a2= b2; b2= d2; } PROD p2+= numint; p5+= numint; p8+= numint; } #undef PROD #define PROD \ *q2= a1 | b1 | d1 | a2 | b2 | (b2 << 1) | (b2 >> 1) | d2; \ q2+= numint; PROC d2= *p2 & c; a1= 0; b1= d1; a2= 0; b2= d2; p5+= numint; p2+= numint; PROC d2= *p2 & c; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; PROC d2= *p2 & c; PROD a1= b1; b1= d1; a2= b2; b2= d2; } PROD p5+= numint; p2+= numint; #undef PROC #undef PROD } else if (numint > 1) { p1= input; q1= output; p2= p1; p5= p2; p4= p2 + 1; p7= p5 + 1; p8= p5 + numg; p10= p8 + 1; q2= q1; #define PROC \ d1= *p5; \ d1|= ((*p7 & LB) != 0)?((RB | (d1 << 1)) | (d1 >> 1)) \ :((d1 << 1) | (d1 >> 1)); #define PROD \ g= a1 | b1 | d1 | a2 | b2 | d2; \ *q2= ((e & LB) != 0)?(g | (RB | (b2 << 1)) | (b2 >> 1)) \ :(g | (b2 << 1) | (b2 >> 1)); \ q2+= numint; PROC d2= *p8; a1= 0; b1= d1; a2= 0; b2= d2; e= *p10; p5+= numint; p8+= numint; p7+= numint; p10+= numint; PROC d2= *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { e= *p10; p5+= numint; p8+= numint; p7+= numint; p10+= numint; PROC d2= *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; } e= *p10; PROD p5+= numint; p8+= numint; p7+= numint; p10+= numint; for (k= 2; k < depth; k++){ PROC d2= *p2 | *p8; a1= 0; b1= d1; a2= 0; b2= d2; e= *p4 | *p10; p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; PROC d2= *p2 | *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { e= *p4 | *p10; p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; PROC d2= *p2 | *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; } e= *p4 | *p10; PROD p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; } PROC d2= *p2; a1= 0; b1= d1; a2= 0; b2= d2; e= *p4; p5+= numint; p2+= numint; p7+= numint; p4+= numint; PROC d2= *p2; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { e= *p4; p5+= numint; p2+= numint; p7+= numint; p4+= numint; PROC d2= *p2; PROD a1= b1; b1= d1; a2= b2; b2= d2; } e= *p4; PROD p5+= numint; p2+= numint; p7+= numint; p4+= numint; #undef PROC #undef PROD for (i=2 ; i < numint; i++) { p3= p1; p6= p3; p9= p6 + numg; p1++; q1++; p2= p1; p5= p2; p8= p5 + numg; p4= p2 + 1; p7= p5 + 1; p10= p8 + 1; q2= q1; #define PROC \ d1= *p5; \ d1|= ((*p6 & RB) != 0)? \ ((*p7 & LB) != 0)?((RB | (d1 << 1)) | (LB | (d1 >> 1))) \ :((d1 << 1) | (LB | (d1 >> 1))) \ : \ ((*p7 & LB) != 0)?((RB | (d1 << 1)) | (d1 >> 1)) \ :((d1 << 1) | (d1 >> 1)); #define PROD \ g= a1 | b1 | d1 | a2 | b2 | d2; \ *q2= ((f & RB) != 0)? \ ((e & LB) != 0)?(g | (RB | (b2 << 1)) | (LB | (b2 >> 1))) \ :(g | (b2 << 1) | (LB | (b2 >> 1))) \ : \ ((e & LB) != 0)?(g | (RB | (b2 << 1)) | (b2 >> 1)) \ :(g | (b2 << 1) | (b2 >> 1)); \ q2+= numint; PROC d2= *p8; a1= 0; b1= d1; a2= 0; b2= d2; e= *p10; f= *p9; p5+= numint; p8+= numint; p6+= numint; p9+= numint; p7+= numint; p10+= numint; PROC d2= *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { e= *p10; f= *p9; p5+= numint; p8+= numint; p6+= numint; p9+= numint; p7+= numint; p10+= numint; PROC d2= *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; } e= *p10; f= *p9; PROD p5+= numint; p8+= numint; p6+= numint; p9+= numint; p7+= numint; p10+= numint; for (k= 2; k < depth; k++){ PROC d2= *p2 | *p8; a1= 0; b1= d1; a2= 0; b2= d2; e= *p4 | *p10; f= *p3 | *p9; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; PROC d2= *p2 | *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { e= *p4 | *p10; f= *p3 | *p9; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; PROC d2= *p2 | *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; } e= *p4 | *p10; f= *p3 | *p9; PROD p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; } PROC d2= *p2; a1= 0; b1= d1; a2= 0; b2= d2; e= *p4; f= *p3; p2+= numint; p5+= numint; p3+= numint; p6+= numint; p4+= numint; p7+= numint; PROC d2= *p2; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { e= *p4; f= *p3; p2+= numint; p5+= numint; p3+= numint; p6+= numint; p4+= numint; p7+= numint; PROC d2= *p2; PROD a1= b1; b1= d1; a2= b2; b2= d2; } e= *p4; f= *p3; PROD p2+= numint; p5+= numint; p3+= numint; p6+= numint; p4+= numint; p7+= numint; } p3= p1; p6= p3; p9= p6 + numg; p1++; q1++; p2= p1; p5= p2; q2= q1; p8= p5 + numg; #undef PROC #undef PROD #define PROC \ d1= *p5; \ d1|= ((*p6 & RB) != 0)?((d1 << 1) | (LB | (d1 >> 1))) \ :((d1 << 1) | (d1 >> 1)); #define PROD \ g= a1 | b1 | d1 | a2 | b2 | d2; \ *q2= ((f & RB) != 0)?(g | (b2 << 1) | (LB | (b2 >> 1))) \ :(g | (b2 << 1) | (b2 >> 1)); \ q2+= numint; PROC d2= *p8; a1= 0; b1= d1; a2= 0; b2= d2; f= *p9; p5+= numint; p8+= numint; p6+= numint; p9+= numint; PROC d2= *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { f= *p9; p5+= numint; p8+= numint; p6+= numint; p9+= numint; PROC d2= *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; } f= *p9; PROD p5+= numint; p8+= numint; p6+= numint; p9+= numint; for (k= 2; k < depth; k++){ PROC d2= *p2 | *p8; a1= 0; b1= d1; a2= 0; b2= d2; f= *p3 | *p9; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; PROC d2= *p2 | *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { f= *p3 | *p9; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; PROC d2= *p2 | *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; } f= *p3 | *p9; PROD p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; } PROC d2= *p2; a1= 0; b1= d1; a2= 0; b2= d2; f= *p3; p2+= numint; p5+= numint; p3+= numint; p6+= numint; PROC d2= *p2; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { f= *p3; p2+= numint; p5+= numint; p3+= numint; p6+= numint; PROC d2= *p2; PROD a1= b1; b1= d1; a2= b2; b2= d2; } f= *p3; PROD p2+= numint; p5+= numint; p3+= numint; p6+= numint; #undef PROC #undef PROD } } template void dilate3D_10_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *q1, *q2; size_t c, a1, b1, d1, b2, d2; ptrdiff_t numint, i, j, k, numg; INIT if (numint == 1) { p2= input; p5= p2; p8= p5 + numg; q2= output; #define PROC \ d1= *p5 & c; \ d1|= ((d1 << 1) | (d1 >> 1)) & c; #define PROD \ *q2= a1 | b1 | d1 | b2; \ q2+= numint; PROC d2= *p8 & c; a1= 0; b1= d1; b2= d2; p5+= numint; p8+= numint; PROC d2= *p8 & c; PROD a1= b1; b1= d1; b2= d2; for (j= 2; j < height; j++) { p5+= numint; p8+= numint; PROC d2= *p8 & c; PROD a1= b1; b1= d1; b2= d2; } PROD p5+= numint; p8+= numint; for (k= 2; k < depth; k++){ PROC d2= (*p2 | *p8) & c; a1= 0; b1= d1; b2= d2; p2+= numint; p5+= numint; p8+= numint; PROC d2= (*p2 | *p8) & c; PROD a1= b1; b1= d1; b2= d2; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; PROC d2= (*p2 | *p8) & c; PROD a1= b1; b1= d1; b2= d2; } PROD p2+= numint; p5+= numint; p8+= numint; } PROC d2= *p2 & c; a1= 0; b1= d1; b2= d2; p5+= numint; p2+= numint; PROC d2= *p2 & c; PROD a1= b1; b1= d1; b2= d2; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; PROC d2= *p2 & c; PROD a1= b1; b1= d1; b2= d2; } PROD p5+= numint; p2+= numint; #undef PROC } else if (numint > 1) { p1= input; q1= output; p2= p1; p5= p2; p4= p2 + 1; p7= p5 + 1; p8= p5 + numg; p10= p8 + 1; q2= q1; #define PROC \ d1= *p5; \ d1|= ((*p7 & LB) != 0)?((RB | (d1 << 1)) | (d1 >> 1)) \ :((d1 << 1) | (d1 >> 1)); PROC d2= *p8; a1= 0; b1= d1; b2= d2; p5+= numint; p8+= numint; p7+= numint; p10+= numint; PROC d2= *p8; PROD a1= b1; b1= d1; b2= d2; for (j= 2; j < height; j++) { p5+= numint; p8+= numint; p7+= numint; p10+= numint; PROC d2= *p8; PROD a1= b1; b1= d1; b2= d2; } PROD p5+= numint; p8+= numint; p7+= numint; p10+= numint; for (k= 2; k < depth; k++){ PROC d2= *p2 | *p8; a1= 0; b1= d1; a2= 0; b2= d2; e= *p4 | *p10; p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; PROC d2= *p2 | *p8; PROD a1= b1; b1= d1; b2= d2; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; PROC d2= *p2 | *p8; PROD a1= b1; b1= d1; b2= d2; } PROD p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; } PROC d2= *p2; a1= 0; b1= d1; b2= d2; p5+= numint; p2+= numint; p7+= numint; p4+= numint; PROC d2= *p2; PROD a1= b1; b1= d1; b2= d2; for (j= 2; j < height; j++) { p5+= numint; p2+= numint; p7+= numint; p4+= numint; PROC d2= *p2; PROD a1= b1; b1= d1; b2= d2; } PROD p5+= numint; p2+= numint; p7+= numint; p4+= numint; #undef PROC for (i=2 ; i < numint; i++) { p3= p1; p6= p3; p9= p6 + numg; p1++; q1++; p2= p1; p5= p2; p8= p5 + numg; p4= p2 + 1; p7= p5 + 1; p10= p8 + 1; q2= q1; #define PROC \ d1= *p5; \ d1|= ((*p6 & RB) != 0)? \ ((*p7 & LB) != 0)?((RB | (d1 << 1)) | (LB | (d1 >> 1))) \ :((d1 << 1) | (LB | (d1 >> 1))) \ : \ ((*p7 & LB) != 0)?((RB | (d1 << 1)) | (d1 >> 1)) \ :((d1 << 1) | (d1 >> 1)); PROC d2= *p8; a1= 0; b1= d1; a2= 0; b2= d2; p5+= numint; p8+= numint; p6+= numint; p9+= numint; p7+= numint; p10+= numint; PROC d2= *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; for (j= 2; j < height; j++) { p5+= numint; p8+= numint; p6+= numint; p9+= numint; p7+= numint; p10+= numint; PROC d2= *p8; PROD a1= b1; b1= d1; a2= b2; b2= d2; } PROD p5+= numint; p8+= numint; p6+= numint; p9+= numint; p7+= numint; p10+= numint; for (k= 2; k < depth; k++){ PROC d2= *p2 | *p8; a1= 0; b1= d1; b2= d2; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; PROC d2= *p2 | *p8; PROD a1= b1; b1= d1; b2= d2; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; PROC d2= *p2 | *p8; PROD a1= b1; b1= d1; b2= d2; } PROD p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; } PROC d2= *p2; a1= 0; b1= d1; b2= d2; p2+= numint; p5+= numint; p3+= numint; p6+= numint; p4+= numint; p7+= numint; PROC d2= *p2; PROD a1= b1; b1= d1; b2= d2; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p3+= numint; p6+= numint; p4+= numint; p7+= numint; PROC d2= *p2; PROD a1= b1; b1= d1; b2= d2; } PROD p2+= numint; p5+= numint; p3+= numint; p6+= numint; p4+= numint; p7+= numint; } p3= p1; p6= p3; p9= p6 + numg; p1++; q1++; p2= p1; p5= p2; q2= q1; p8= p5 + numg; #undef PROC #define PROC \ d1= *p5; \ d1|= ((*p6 & RB) != 0)?((d1 << 1) | (LB | (d1 >> 1))) \ :((d1 << 1) | (d1 >> 1)); PROC d2= *p8; a1= 0; b1= d1; b2= d2; p5+= numint; p8+= numint; p6+= numint; p9+= numint; PROC d2= *p8; PROD a1= b1; b1= d1; b2= d2; for (j= 2; j < height; j++) { p5+= numint; p8+= numint; p6+= numint; p9+= numint; PROC d2= *p8; PROD a1= b1; b1= d1; b2= d2; } PROD p5+= numint; p8+= numint; p6+= numint; p9+= numint; for (k= 2; k < depth; k++){ PROC d2= *p2 | *p8; a1= 0; b1= d1; b2= d2; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; PROC d2= *p2 | *p8; PROD a1= b1; b1= d1; b2= d2; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; PROC d2= *p2 | *p8; PROD a1= b1; b1= d1; b2= d2; } PROD p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; } PROC d2= *p2; a1= 0; b1= d1; b2= d2; p2+= numint; p5+= numint; p3+= numint; p6+= numint; PROC d2= *p2; PROD a1= b1; b1= d1; b2= d2; for (j= 2; j < height; j++) { f= *p3; p2+= numint; p5+= numint; p3+= numint; p6+= numint; PROC d2= *p2; PROD a1= b1; b1= d1; b2= d2; } PROD p2+= numint; p5+= numint; p3+= numint; p6+= numint; #undef PROC #undef PROD } } template void dilate3D_a_bin (size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p5, *p8, *q1, *q2; size_t c; ptrdiff_t numint, i, j, k, numg; INIT p1= input; q1= output; for (i= 1 ; i < numint; i++) { p2= p1; p5= p2; p8= p5 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= *p5 | *p8; q2+= numint; p5+= numint; p8+= numint; } for (k= 2; k < depth; k++){ for (j= 0; j < height; j++) { *q2= *p2 | *p5 | *p8; q2+= numint; p2+= numint; p5+= numint; p8+= numint; } } for (j= 0; j < height; j++) { *q2= *p2 | *p5; q2+= numint; p2+= numint; p5+= numint; } p1++; q1++; } p2= p1; p5= p2; q2= q1; p8= p5 + numg; for (j= 0; j < height; j++) { *q2= (*p5 | *p8) & c; q2+= numint; p5+= numint; p8+= numint; } for (k= 2; k < depth; k++) for (j= 0; j < height; j++) { *q2= (*p2 | *p5 | *p8) & c; q2+= numint; p2+= numint; p5+= numint; p8+= numint; } for (j= 2; j < height; j++) { *q2= (*p2 | *p5) & c; q2+= numint; p2+= numint; p5+= numint; } } #undef INIT #define INIT \ numint= (width + Numb - 1) / Numb; \ c= ((width % Numb) == 0)?(AB):(AB << (Numb - (width % Numb))); \ nc= ~(c & ~(c << 1)); const size_t NLB = ~LB; template void endpoints2d_8_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *p4, *q1, *q2, a1, a2, a3, b1, b2, b3, c, nc, d1, d2, d3, e0, e1, bp; ptrdiff_t numint, i, j; #define TEST(x,b0,b1) \ bp= b0 ^ (x & ~b1); \ b1|= x & b0; \ b0= bp; #define TESTIT \ e0= 0; e1= 0; \ TEST(a1,e0,e1) \ TEST(a2,e0,e1) \ TEST(a3,e0,e1) \ TEST(b1,e0,e1) \ TEST(b3,e0,e1) \ TEST(d1,e0,e1) \ TEST(d2,e0,e1) \ TEST(d3,e0,e1) INIT if (numint == 1) { p2= input; q2= output; #define PROC(x1,x2,x3) \ x2= *p2 & c; \ x3= (x2 << 1); \ x1= (x2 >> 1); PROC(a1,a2,a3) p2+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= NLB & e0 & b2 & nc; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; #undef PROC } q2+= numint; *q2= 0; } else if (numint > 1) { p1= input; q1= output; p2= p1; q2= q1; p4= p1 + 1; #define PROC(x1,x2,x3) \ x2= *p2; \ x3= (*p4 & LB)?(RB | (x2 << 1)):(x2 << 1); \ x1= (x2 >> 1); PROC(a1,a2,a3) p2+= numint; p4+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p4+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= NLB & e0 & b2; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; #undef PROC } q2+= numint; *q2= 0; for (i= 1; i < (numint - 1); i++) { p3= p1; p1++; q1++; p2= p1; q2= q1; p4= p1 + 1; #define PROC(x1,x2,x3) \ x2= *p2; \ x3= (*p4 & LB)?(RB | (x2 << 1)):(x2 << 1); \ x1= (*p3 & RB)?(LB | (x2 >> 1)):(x2 >> 1); PROC(a1,a2,a3) p2+= numint; p3+= numint; p4+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p3+= numint; p4+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= e0 & b2; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; #undef PROC } q2+= numint; *q2= 0; } p3= p1; p1++; q1++; p2= p1; q2= q1; #define PROC(x1,x2,x3) \ x2= *p2 & c; \ x3= (x2 << 1); \ x1= (*p3 & RB)?(LB | (x2 >> 1)):(x2 >> 1); PROC(a1,a2,a3) p2+= numint; p3+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p3+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= e0 & b2 & nc; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; } q2+= numint; *q2= 0; } } #undef PROC #undef TEST #undef TESTIT template void endpoints2d_4_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *p4, *q1, *q2, a1, a2, a3, b1, b2, b3, c, nc, d1, d2, d3, e0, e1, bp; ptrdiff_t numint, i, j; #define TEST(x,b0,b1) \ bp= b0 ^ (x & ~b1); \ b1|= x & b0; \ b0= bp; #define TESTIT \ e0= 0; e1= 0; \ TEST(a2,e0,e1) \ TEST(b1,e0,e1) \ TEST(b3,e0,e1) \ TEST(d2,e0,e1) INIT if (numint == 1) { p2= input; q2= output; #define PROC(x1,x2,x3) \ x2= *p2 & c; \ x3= (x2 << 1); \ x1= (x2 >> 1); PROC(a1,a2,a3) p2+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= NLB & e0 & b2 & nc; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; #undef PROC } q2+= numint; *q2= 0; } else if (numint > 1) { p1= input; q1= output; p2= p1; q2= q1; p4= p1 + 1; #define PROC(x1,x2,x3) \ x2= *p2; \ x3= (*p4 & LB)?(RB | (x2 << 1)):(x2 << 1); \ x1= (x2 >> 1); PROC(a1,a2,a3) p2+= numint; p4+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p4+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= NLB & e0 & b2; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; #undef PROC } q2+= numint; *q2= 0; for (i= 1; i < (numint - 1); i++) { p3= p1; p1++; q1++; p2= p1; q2= q1; p4= p1 + 1; #define PROC(x1,x2,x3) \ x2= *p2; \ x3= (*p4 & LB)?(RB | (x2 << 1)):(x2 << 1); \ x1= (*p3 & RB)?(LB | (x2 >> 1)):(x2 >> 1); PROC(a1,a2,a3) p2+= numint; p3+= numint; p4+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p3+= numint; p4+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= e0 & b2; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; #undef PROC } q2+= numint; *q2= 0; } p3= p1; p1++; q1++; p2= p1; q2= q1; #define PROC(x1,x2,x3) \ x2= *p2 & c; \ x3= (x2 << 1); \ x1= (*p3 & RB)?(LB | (x2 >> 1)):(x2 >> 1); PROC(a1,a2,a3) p2+= numint; p3+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p3+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= e0 & b2 & nc; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; } q2+= numint; *q2= 0; } } #undef PROC #undef TEST #undef TESTIT template void midpoints2d_8_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *p4, *q1, *q2, a1, a2, a3, b1, b2, b3, c, nc, d1, d2, d3, e0, e1, bp; ptrdiff_t numint, i, j; #define TEST(x,b0,b1) \ bp= (x & ~(b1 & b0)); \ b1|= bp & b0; \ b0= bp ^ b0; #define TESTIT \ e0= 0; e1= 0; \ TEST(a1,e0,e1) \ TEST(a2,e0,e1) \ TEST(a3,e0,e1) \ TEST(b1,e0,e1) \ TEST(b3,e0,e1) \ TEST(d1,e0,e1) \ TEST(d2,e0,e1) \ TEST(d3,e0,e1) INIT if (numint == 1) { p2= input; q2= output; #define PROC(x1,x2,x3) \ x2= *p2 & c; \ x3= (x2 << 1); \ x1= (x2 >> 1); PROC(a1,a2,a3) p2+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= NLB & (e1 & ~e0) & b2 & nc; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; #undef PROC } q2+= numint; *q2= 0; } else if (numint > 1) { p1= input; q1= output; p2= p1; q2= q1; p4= p1 + 1; #define PROC(x1,x2,x3) \ x2= *p2; \ x3= (*p4 & LB)?(RB | (x2 << 1)):(x2 << 1); \ x1= (x2 >> 1); PROC(a1,a2,a3) p2+= numint; p4+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p4+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= NLB & (e1 & ~e0) & b2; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; #undef PROC } q2+= numint; *q2= 0; for (i= 1; i < (numint - 1); i++) { p3= p1; p1++; q1++; p2= p1; q2= q1; p4= p1 + 1; #define PROC(x1,x2,x3) \ x2= *p2; \ x3= (*p4 & LB)?(RB | (x2 << 1)):(x2 << 1); \ x1= (*p3 & RB)?(LB | (x2 >> 1)):(x2 >> 1); PROC(a1,a2,a3) p2+= numint; p3+= numint; p4+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p3+= numint; p4+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= (e1 & ~e0) & b2; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; #undef PROC } q2+= numint; *q2= 0; } p3= p1; p1++; q1++; p2= p1; q2= q1; #define PROC(x1,x2,x3) \ x2= *p2 & c; \ x3= (x2 << 1); \ x1= (*p3 & RB)?(LB | (x2 >> 1)):(x2 >> 1); PROC(a1,a2,a3) p2+= numint; p3+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p3+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= (e1 & ~e0) & b2 & nc; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; } q2+= numint; *q2= 0; } } #undef PROC #undef TEST #undef TESTIT template void midpoints2d_4_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { size_t *p1, *p2, *p3, *p4, *q1, *q2, a1, a2, a3, b1, b2, b3, c, nc, d1, d2, d3, e0, e1, bp; ptrdiff_t numint, i, j; #define TEST(x,b0,b1) \ bp= (x & ~(b1 & b0)); \ b1|= bp & b0; \ b0= bp ^ b0; #define TESTIT \ e0= 0; e1= 0; \ TEST(a2,e0,e1) \ TEST(b1,e0,e1) \ TEST(b3,e0,e1) \ TEST(d2,e0,e1) INIT if (numint == 1) { p2= input; q2= output; #define PROC(x1,x2,x3) \ x2= *p2 & c; \ x3= (x2 << 1); \ x1= (x2 >> 1); PROC(a1,a2,a3) p2+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= NLB & (e1 & ~e0) & b2 & nc; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; #undef PROC } q2+= numint; *q2= 0; } else if (numint > 1) { p1= input; q1= output; p2= p1; q2= q1; p4= p1 + 1; #define PROC(x1,x2,x3) \ x2= *p2; \ x3= (*p4 & LB)?(RB | (x2 << 1)):(x2 << 1); \ x1= (x2 >> 1); PROC(a1,a2,a3) p2+= numint; p4+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p4+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= NLB & (e1 & ~e0) & b2; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; #undef PROC } q2+= numint; *q2= 0; for (i= 1; i < (numint - 1); i++) { p3= p1; p1++; q1++; p2= p1; q2= q1; p4= p1 + 1; #define PROC(x1,x2,x3) \ x2= *p2; \ x3= (*p4 & LB)?(RB | (x2 << 1)):(x2 << 1); \ x1= (*p3 & RB)?(LB | (x2 >> 1)):(x2 >> 1); PROC(a1,a2,a3) p2+= numint; p3+= numint; p4+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p3+= numint; p4+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= (e1 & ~e0) & b2; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; #undef PROC } q2+= numint; *q2= 0; } p3= p1; p1++; q1++; p2= p1; q2= q1; #define PROC(x1,x2,x3) \ x2= *p2 & c; \ x3= (x2 << 1); \ x1= (*p3 & RB)?(LB | (x2 >> 1)):(x2 >> 1); PROC(a1,a2,a3) p2+= numint; p3+= numint; PROC(b1,b2,b3) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p3+= numint; q2+= numint; PROC(d1,d2,d3) TESTIT *q2= (e1 & ~e0) & b2 & nc; a1= b1; a2= b2; a3= b3; b1= d1; b2= d2; b3= d3; } q2+= numint; *q2= 0; } } #undef PROC #undef TEST #undef TESTIT #undef INIT template void add2d_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, char *output) { char *pio= output; size_t *pib= input; size_t k= LB, c= 0; ptrdiff_t i,j; for (i= 0; i < height; i++) { for (j= 0; j < width; j++, pio++) { if (*pib & k) (*pio)+= 1; k= k >> 1; if (k == 0) { k= LB; pib++; c= 0; } } if (k != LB) { k= LB; pib++; c= 0; } } return; } template void sub2d_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, char *output) { char *pio= output; size_t *pib= input; size_t k= LB, c= 0; ptrdiff_t i,j; for (i= 0; i < height; i++) { for (j= 0; j < width; j++, pio++) { if (*pib & k) (*pio)-= 1; k= k >> 1; if (k == 0) { k= LB; pib++; c= 0; } } if (k != LB) { k= LB; pib++; c= 0; } } return; } #ifdef _WIN64 const size_t PUNCH = 0xaaaaaaaaaaaaaaaaui64; #else const size_t PUNCH = 0xaaaaaaaa; #endif template void euler2D_8(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *pom, char *buf) { memset(buf, 0, width * height); dilate2D_0_bin(input, width, height, pom); add2d_bin(pom, width, height, buf); dilate2D_0h_bin(input, width, height, pom); sub2d_bin(pom, width, height, buf); dilate2D_0v_bin(input, width, height, pom); sub2d_bin(pom, width, height, buf); add2d_bin(input, width, height, buf); } template void simplepoints2d_8_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t x0, ptrdiff_t y0, size_t *output, char *buf1, char *buf2, size_t *bufp) { ptrdiff_t ints= (width + Numb - 1) / Numb; ptrdiff_t i, j, k; char *p1, *p2; euler2D_8(input, width, height, output, buf1); memcpy(bufp, input, ints * height * sizeof(size_t)); size_t punch= (PUNCH >> x0); for (i= y0; i < height; i+= 2) for (j= 0; j < ints; j++) bufp[i * ints + j]&= ~punch; euler2D_8(bufp, width, height, output, buf2); memset(output, 0, ints * height * sizeof(size_t)); for (i= 0; i < height; i++) { k= (x0 < 1)?(x0 + 2):x0; for (j= k, p1= buf1 + i * width + k, p2= buf2 + i * width + k; j < width; j+= 2, p1+= 2, p2+= 2) { *p1+= *(p1 - 1); *p2+= *(p2 - 1); } } k= (y0 < 1)?(y0 + 2):y0; for (i= k; i < height; i+= 2) for (j= 0, p1= buf1 + i * width, p2= buf2 + i * width; j < width; j++, p1++, p2++) { *p1+= *(p1 - width); *p2+= *(p2 - width); } for (i= y0; i < height; i+= 2) for (j= x0, p1= buf1 + i * width + x0, p2= buf2 + i * width + x0; j < width; j+= 2, p1+= 2, p2+= 2) if (*p1 == *p2) output[i * ints + j / Numb]|= input[i * ints + j / Numb] & (LB >> (j % Numb)); } template void euler2D_4(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *pom, char *buf) { memset(buf, 0, width * height); erode2D_0_bin(input, width, height, pom); add2d_bin(pom, width, height, buf); erode2D_0h_bin(input, width, height, pom); sub2d_bin(pom, width, height, buf); erode2D_0v_bin(input, width, height, pom); sub2d_bin(pom, width, height, buf); add2d_bin(input, width, height, buf); } template void simplepoints2d_4_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t x0, ptrdiff_t y0, size_t *output, char *buf1, char *buf2, size_t *bufp) { ptrdiff_t ints= (width + Numb - 1) / Numb; ptrdiff_t i, j; char *p1, *p2; euler2D_4(input, width, height, output, buf1); memcpy(bufp, input, ints * height * sizeof(size_t)); size_t punch= (PUNCH >> x0); for (i= y0; i < height; i+= 2) for (j= 0; j < ints; j++) bufp[i * ints + j]&= ~punch; euler2D_4(bufp, width, height, output, buf2); memset(output, 0, ints * height * sizeof(size_t)); for (i= 0; i < height; i++) { for (j= x0, p1= buf1 + i * width + x0, p2= buf2 + i * width + x0; j < (width - 1); j+= 2, p1+= 2, p2+= 2) { *p1+= *(p1 + 1); *p2+= *(p2 + 1); } } for (i= y0; i < (height - 1); i+= 2) for (j= 0, p1= buf1 + i * width, p2= buf2 + i * width; j < width; j++, p1++, p2++) { *p1+= *(p1 + width); *p2+= *(p2 + width); } for (i= y0; i < height; i+= 2) for (j= x0, p1= buf1 + i * width + x0, p2= buf2 + i * width + x0; j < width; j+= 2, p1+= 2, p2+= 2) if (*p1 == *p2) output[i * ints + j / Numb]|= input[i * ints + j / Numb] & (LB >> (j % Numb)); } #define INIT \ numint= (width + Numb - 1) / Numb; \ numg= numint * height; \ c= ((width % Numb) == 0)?(AB):(AB << (Numb - (width % Numb))); \ nc= ~(c & ~(c << 1)); template void endpoints3d_26_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *q1, *q2; size_t a11, a12, a13, a21, a22, a23, a31, a32, a33, b11, b12, b13, b21, b22, b23, b31, b32, b33, d11, d12, d13, d21, d22, d23, d31, d32, d33, e0, e1, bp, c, nc; ptrdiff_t numint, i, j, k, numg; #define TEST(x,b0,b1) \ bp= b0 ^ (x & ~b1); \ b1|= x & b0; \ b0= bp; #define TESTIT \ e0= 0; e1= 0; \ TEST(a11,e0,e1) \ TEST(a12,e0,e1) \ TEST(a13,e0,e1) \ TEST(a21,e0,e1) \ TEST(a22,e0,e1) \ TEST(a23,e0,e1) \ TEST(a31,e0,e1) \ TEST(a32,e0,e1) \ TEST(a33,e0,e1) \ TEST(b11,e0,e1) \ TEST(b12,e0,e1) \ TEST(b13,e0,e1) \ TEST(b21,e0,e1) \ TEST(b23,e0,e1) \ TEST(b31,e0,e1) \ TEST(b32,e0,e1) \ TEST(b33,e0,e1) \ TEST(d11,e0,e1) \ TEST(d12,e0,e1) \ TEST(d13,e0,e1) \ TEST(d21,e0,e1) \ TEST(d22,e0,e1) \ TEST(d23,e0,e1) \ TEST(d31,e0,e1) \ TEST(d32,e0,e1) \ TEST(d33,e0,e1) #define SHIFTIT \ a11= b11; a12= b12; a13= b13; \ a21= b21; a22= b22; a23= b23; \ a31= b31; a32= b32; a33= b33; \ b11= d11; b12= d12; b13= d13; \ b21= d21; b22= d22; b23= d23; \ b31= d31; b32= d32; b33= d33; INIT if (numint == 1) { p2= input; p5= p2 + numg; p8= p5 + numg; q2= output; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2 & c; \ x31= (x21 << 1); \ x11= (x21 >> 1); \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= (x22 >> 1); \ x23= *p8 & c; \ x33= (x23 << 1); \ x13= (x23 >> 1); for (k= 2; k < depth; k++){ PROC(a11,a12,a13,a21,a22,a23,a31,a32,a33) p2+= numint; p5+= numint; p8+= numint; PROC(b11,b12,b13,b21,b22,b23,b31,b32,b33) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; q2+= numint; PROC(d11,d12,d13,d21,d22,d23,d31,d32,d33) TESTIT *q2= NLB & e0 & b22 & nc; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } else if (numint > 1) { p1= input; q1= output; p2= p1; p5= p2 + numg; p8= p5 + numg; p4= p2 + 1; p7= p5 + 1; p10= p8 + 1; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2; \ x31= (*p4 & LB)?(RB | (x21 << 1)):(x21 << 1); \ x11= (x21 >> 1); \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (x22 >> 1); \ x23= *p8; \ x33= (*p10 & LB)?(RB | (x23 << 1)):(x23 << 1); \ x13= (x23 >> 1); for (k= 2; k < depth; k++){ PROC(a11,a12,a13,a21,a22,a23,a31,a32,a33) p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; PROC(b11,b12,b13,b21,b22,b23,b31,b32,b33) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; PROC(d11,d12,d13,d21,d22,d23,d31,d32,d33) TESTIT *q2= NLB & e0 & b22; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } for (i=2 ; i < numint; i++) { p3= p1; p6= p3 + numg; p9= p6 + numg; p1++; q1++; p2= p1; p5= p2 + numg; p8= p5 + numg; p4= p2 + 1; p7= p5 + 1; p10= p8 + 1; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2; \ x31= (*p4 & LB)?(RB | (x21 << 1)):(x21 << 1); \ x11= (*p3 & RB)?(LB | (x21 >> 1)):(x21 >> 1); \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1); \ x23= *p8; \ x33= (*p10 & LB)?(RB | (x23 << 1)):(x23 << 1); \ x13= (*p9 & RB)?(LB | (x23 >> 1)):(x23 >> 1); for (k= 2; k < depth; k++){ PROC(a11,a12,a13,a21,a22,a23,a31,a32,a33) p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; PROC(b11,b12,b13,b21,b22,b23,b31,b32,b33) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; PROC(d11,d12,d13,d21,d22,d23,d31,d32,d33) TESTIT *q2= e0 & b22; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } p3= p1; p6= p3 + numg; p9= p6 + numg; p1++; q1++; p2= p1; p5= p2 + numg; p8= p5 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2 & c; \ x31= (x21 << 1); \ x11= (*p3 & RB)?(LB | (x21 >> 1)):(x21 >> 1); \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= (*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1); \ x23= *p8 & c; \ x33= (x23 << 1); \ x13= (*p9 & RB)?(LB | (x23 >> 1)):(x23 >> 1); for (k= 2; k < depth; k++){ PROC(a11,a12,a13,a21,a22,a23,a31,a32,a33) p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; PROC(b11,b12,b13,b21,b22,b23,b31,b32,b33) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; q2+= numint; PROC(d11,d12,d13,d21,d22,d23,d31,d32,d33) TESTIT *q2= e0 & b22 & nc; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } } #undef PROC #undef TEST #undef TESTIT #undef SHIFTIT template void endpoints3d_6_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p5, *p6, *p7, *p8, *q1, *q2; size_t a12, a21, a22, a23, a32, b12, b21, b22, b23, b32, d12, d21, d22, d23, d32, e0, e1, bp, c, nc; ptrdiff_t numint, i, j, k, numg; #define TEST(x,b0,b1) \ bp= b0 ^ (x & ~b1); \ b1|= x & b0; \ b0= bp; #define TESTIT \ e0= 0; e1= 0; \ TEST(a22,e0,e1) \ TEST(b12,e0,e1) \ TEST(b21,e0,e1) \ TEST(b23,e0,e1) \ TEST(b32,e0,e1) \ TEST(d22,e0,e1) #define SHIFTIT \ a22= b22; \ b12= d12; b21= d21; b22= d22; b23= d23; b32= d32; INIT if (numint == 1) { p2= input; p5= p2 + numg; p8= p5 + numg; q2= output; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x12,x21,x22,x23,x32) \ x21= *p2 & c; \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= (x22 >> 1); \ x23= *p8 & c; for (k= 2; k < depth; k++){ PROC(a12,a21,a22,a23,a32) p2+= numint; p5+= numint; p8+= numint; PROC(b12,b21,b22,b23,b32) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; q2+= numint; PROC(d12,d21,d22,d23,d32) TESTIT *q2= NLB & e0 & b22 & nc; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } else if (numint > 1) { p1= input; q1= output; p2= p1; p5= p2 + numg; p8= p5 + numg; p7= p5 + 1; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x12,x21,x22,x23,x32) \ x21= *p2; \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (x22 >> 1); \ x23= *p8; for (k= 2; k < depth; k++){ PROC(a12,a21,a22,a23,a32) p2+= numint; p5+= numint; p8+= numint; p7+= numint; PROC(b12,b21,b22,b23,b32) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p7+= numint; q2+= numint; PROC(d12,d21,d22,d23,d32) TESTIT *q2= NLB & e0 & b22; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p7+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } for (i=2 ; i < numint; i++) { p6= p1 + numg; p1++; q1++; p2= p1; p5= p2 + numg; p8= p5 + numg; p7= p5 + 1; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x12,x21,x22,x23,x32) \ x21= *p2; \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1); \ x23= *p8; for (k= 2; k < depth; k++){ PROC(a12,a21,a22,a23,a32) p2+= numint; p5+= numint; p8+= numint; p6+= numint; p7+= numint; PROC(b12,b21,b22,b23,b32) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p6+= numint; p7+= numint; q2+= numint; PROC(d12,d21,d22,d23,d32) TESTIT *q2= e0 & b22; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p6+= numint; p7+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } p6= p1 + numg; p1++; q1++; p2= p1; p5= p2 + numg; p8= p5 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x12,x21,x22,x23,x32) \ x21= *p2 & c; \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= (*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1); \ x23= *p8 & c; for (k= 2; k < depth; k++){ PROC(a12,a21,a22,a23,a32) p2+= numint; p5+= numint; p8+= numint; p6+= numint; PROC(b12,b21,b22,b23,b32) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p6+= numint; q2+= numint; PROC(d12,d21,d22,d23,d32) TESTIT *q2= e0 & b22 & nc; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p6+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } } #undef PROC #undef TEST #undef TESTIT #undef SHIFTIT template void midpoints3d_26_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *q1, *q2; size_t a11, a12, a13, a21, a22, a23, a31, a32, a33, b11, b12, b13, b21, b22, b23, b31, b32, b33, d11, d12, d13, d21, d22, d23, d31, d32, d33, e0, e1, bp, c, nc; ptrdiff_t numint, i, j, k, numg; #define TEST(x,b0,b1) \ bp= (x & ~(b1 & b0)); \ b1|= bp & b0; \ b0= bp ^ b0; #define TESTIT \ e0= 0; e1= 0; \ TEST(a11,e0,e1) \ TEST(a12,e0,e1) \ TEST(a13,e0,e1) \ TEST(a21,e0,e1) \ TEST(a22,e0,e1) \ TEST(a23,e0,e1) \ TEST(a31,e0,e1) \ TEST(a32,e0,e1) \ TEST(a33,e0,e1) \ TEST(b11,e0,e1) \ TEST(b12,e0,e1) \ TEST(b13,e0,e1) \ TEST(b21,e0,e1) \ TEST(b23,e0,e1) \ TEST(b31,e0,e1) \ TEST(b32,e0,e1) \ TEST(b33,e0,e1) \ TEST(d11,e0,e1) \ TEST(d12,e0,e1) \ TEST(d13,e0,e1) \ TEST(d21,e0,e1) \ TEST(d22,e0,e1) \ TEST(d23,e0,e1) \ TEST(d31,e0,e1) \ TEST(d32,e0,e1) \ TEST(d33,e0,e1) #define SHIFTIT \ a11= b11; a12= b12; a13= b13; \ a21= b21; a22= b22; a23= b23; \ a31= b31; a32= b32; a33= b33; \ b11= d11; b12= d12; b13= d13; \ b21= d21; b22= d22; b23= d23; \ b31= d31; b32= d32; b33= d33; INIT if (numint == 1) { p2= input; p5= p2 + numg; p8= p5 + numg; q2= output; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2 & c; \ x31= (x21 << 1); \ x11= (x21 >> 1); \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= (x22 >> 1); \ x23= *p8 & c; \ x33= (x23 << 1); \ x13= (x23 >> 1); for (k= 2; k < depth; k++){ PROC(a11,a12,a13,a21,a22,a23,a31,a32,a33) p2+= numint; p5+= numint; p8+= numint; PROC(b11,b12,b13,b21,b22,b23,b31,b32,b33) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; q2+= numint; PROC(d11,d12,d13,d21,d22,d23,d31,d32,d33) TESTIT *q2= NLB & (e1 & ~e0) & b22 & nc; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } else if (numint > 1) { p1= input; q1= output; p2= p1; p5= p2 + numg; p8= p5 + numg; p4= p2 + 1; p7= p5 + 1; p10= p8 + 1; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2; \ x31= (*p4 & LB)?(RB | (x21 << 1)):(x21 << 1); \ x11= (x21 >> 1); \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (x22 >> 1); \ x23= *p8; \ x33= (*p10 & LB)?(RB | (x23 << 1)):(x23 << 1); \ x13= (x23 >> 1); for (k= 2; k < depth; k++){ PROC(a11,a12,a13,a21,a22,a23,a31,a32,a33) p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; PROC(b11,b12,b13,b21,b22,b23,b31,b32,b33) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; PROC(d11,d12,d13,d21,d22,d23,d31,d32,d33) TESTIT *q2= NLB & (e1 & ~e0) & b22; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } for (i=2 ; i < numint; i++) { p3= p1; p6= p3 + numg; p9= p6 + numg; p1++; q1++; p2= p1; p5= p2 + numg; p8= p5 + numg; p4= p2 + 1; p7= p5 + 1; p10= p8 + 1; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2; \ x31= (*p4 & LB)?(RB | (x21 << 1)):(x21 << 1); \ x11= (*p3 & RB)?(LB | (x21 >> 1)):(x21 >> 1); \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1); \ x23= *p8; \ x33= (*p10 & LB)?(RB | (x23 << 1)):(x23 << 1); \ x13= (*p9 & RB)?(LB | (x23 >> 1)):(x23 >> 1); for (k= 2; k < depth; k++){ PROC(a11,a12,a13,a21,a22,a23,a31,a32,a33) p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; PROC(b11,b12,b13,b21,b22,b23,b31,b32,b33) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; PROC(d11,d12,d13,d21,d22,d23,d31,d32,d33) TESTIT *q2= (e1 & ~e0) & b22; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; p4+= numint; p7+= numint; p10+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } p3= p1; p6= p3 + numg; p9= p6 + numg; p1++; q1++; p2= p1; p5= p2 + numg; p8= p5 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2 & c; \ x31= (x21 << 1); \ x11= (*p3 & RB)?(LB | (x21 >> 1)):(x21 >> 1); \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= (*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1); \ x23= *p8 & c; \ x33= (x23 << 1); \ x13= (*p9 & RB)?(LB | (x23 >> 1)):(x23 >> 1); for (k= 2; k < depth; k++){ PROC(a11,a12,a13,a21,a22,a23,a31,a32,a33) p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; PROC(b11,b12,b13,b21,b22,b23,b31,b32,b33) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; q2+= numint; PROC(d11,d12,d13,d21,d22,d23,d31,d32,d33) TESTIT *q2= (e1 & ~e0) & b22 & nc; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p3+= numint; p6+= numint; p9+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } } #undef PROC #undef TEST #undef TESTIT #undef SHIFTIT template void midpoints3d_6_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output) { size_t *p1, *p2, *p5, *p6, *p7, *p8, *q1, *q2; size_t a12, a21, a22, a23, a32, b12, b21, b22, b23, b32, d12, d21, d22, d23, d32, e0, e1, bp, c, nc; ptrdiff_t numint, i, j, k, numg; #define TEST(x,b0,b1) \ bp= (x & ~(b1 & b0)); \ b1|= bp & b0; \ b0= bp ^ b0; #define TESTIT \ e0= 0; e1= 0; \ TEST(a22,e0,e1) \ TEST(b12,e0,e1) \ TEST(b21,e0,e1) \ TEST(b23,e0,e1) \ TEST(b32,e0,e1) \ TEST(d22,e0,e1) #define SHIFTIT \ a22= b22; \ b12= d12; b21= d21; b22= d22; b23= d23; b32= d32; INIT if (numint == 1) { p2= input; p5= p2 + numg; p8= p5 + numg; q2= output; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x12,x21,x22,x23,x32) \ x21= *p2 & c; \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= (x22 >> 1); \ x23= *p8 & c; for (k= 2; k < depth; k++){ PROC(a12,a21,a22,a23,a32) p2+= numint; p5+= numint; p8+= numint; PROC(b12,b21,b22,b23,b32) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; q2+= numint; PROC(d12,d21,d22,d23,d32) TESTIT *q2= NLB & (e1 & ~e0) & b22 & nc; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } else if (numint > 1) { p1= input; q1= output; p2= p1; p5= p2 + numg; p8= p5 + numg; p7= p5 + 1; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x12,x21,x22,x23,x32) \ x21= *p2; \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (x22 >> 1); \ x23= *p8; for (k= 2; k < depth; k++){ PROC(a12,a21,a22,a23,a32) p2+= numint; p5+= numint; p8+= numint; p7+= numint; PROC(b12,b21,b22,b23,b32) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p7+= numint; q2+= numint; PROC(d12,d21,d22,d23,d32) TESTIT *q2= NLB & (e1 & ~e0) & b22; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p7+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } for (i=2 ; i < numint; i++) { p6= p1 + numg; p1++; q1++; p2= p1; p5= p2 + numg; p8= p5 + numg; p7= p5 + 1; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x12,x21,x22,x23,x32) \ x21= *p2; \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1); \ x23= *p8; for (k= 2; k < depth; k++){ PROC(a12,a21,a22,a23,a32) p2+= numint; p5+= numint; p8+= numint; p6+= numint; p7+= numint; PROC(b12,b21,b22,b23,b32) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p6+= numint; p7+= numint; q2+= numint; PROC(d12,d21,d22,d23,d32) TESTIT *q2= (e1 & ~e0) & b22; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p6+= numint; p7+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } p6= p1 + numg; p1++; q1++; p2= p1; p5= p2 + numg; p8= p5 + numg; q2= q1; for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } #define PROC(x12,x21,x22,x23,x32) \ x21= *p2 & c; \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= (*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1); \ x23= *p8 & c; for (k= 2; k < depth; k++){ PROC(a12,a21,a22,a23,a32) p2+= numint; p5+= numint; p8+= numint; p6+= numint; PROC(b12,b21,b22,b23,b32) *q2= 0; for (j= 2; j < height; j++) { p2+= numint; p5+= numint; p8+= numint; p6+= numint; q2+= numint; PROC(d12,d21,d22,d23,d32) TESTIT *q2= (e1 & ~e0) & b22 & nc; SHIFTIT #undef PROC } q2+= numint; *q2= 0; p2+= numint; p5+= numint; p8+= numint; p6+= numint; q2+= numint; } for (j= 0; j < height; j++) { *q2= 0; q2+= numint; } } } #undef PROC #undef TEST #undef TESTIT #undef SHIFTIT //palagyi, kuba 1998 template void simplepointsp3d_26_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *output, int dir) { size_t *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *q1, *q2; size_t a11, a12, a13, a21, a22, a23, a31, a32, a33, b11, b12, b13, b21, b22, b23, b31, b32, b33, c11, c12, c13, c21, c22, c23, c31, c32, c33, c, nc, d; ptrdiff_t numint, i, j, k, numg; #define SHIFTIT \ a11= b11; a12= b12; a13= b13; \ a21= b21; a22= b22; a23= b23; \ a31= b31; a32= b32; a33= b33; \ b11= c11; b12= c12; b13= c13; \ b21= c21; b22= c22; b23= c23; \ b31= c31; b32= c32; b33= c33; #define CLEAR(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= 0; x31= 0; x11= 0; \ x22= 0; x32= 0; x12= 0; \ x23= 0; x33= 0; x13= 0; #define PROC0(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2 & c; \ x31= (x21 << 1); \ x11= ((x21 >> 1)) & c; \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= ((x22 >> 1)) & c; \ x23= *p8 & c; \ x33= (x23 << 1); \ x13= ((x23 >> 1)) & c; #define PROC0a(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= 0; \ x31= 0; \ x11= 0; \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= ((x22 >> 1)) & c; \ x23= *p8 & c; \ x33= (x23 << 1); \ x13= ((x23 >> 1)) & c; #define PROC0b(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2 & c; \ x31= (x21 << 1); \ x11= ((x21 >> 1)) & c; \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= ((x22 >> 1)) & c; \ x23= 0; \ x33= 0; \ x13= 0; #define PROC1(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2; \ x31= (*p4 & LB)?(RB | (x21 << 1)):(x21 << 1); \ x11= (x21 >> 1); \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (x22 >> 1); \ x23= *p8; \ x33= (*p10 & LB)?(RB | (x23 << 1)):(x23 << 1); \ x13= (x23 >> 1); #define PROC1a(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= 0; \ x31= 0; \ x11= 0; \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (x22 >> 1); \ x23= *p8; \ x33= (*p10 & LB)?(RB | (x23 << 1)):(x23 << 1); \ x13= (x23 >> 1); #define PROC1b(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2; \ x31= (*p4 & LB)?(RB | (x21 << 1)):(x21 << 1); \ x11= (x21 >> 1); \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (x22 >> 1); \ x23= 0; \ x33= 0; \ x13= 0; #define PROC2(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2; \ x31= (*p4 & LB)?(RB | (x21 << 1)):(x21 << 1); \ x11= (*p3 & RB)?(LB | (x21 >> 1)):(x21 >> 1); \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1); \ x23= *p8; \ x33= (*p10 & LB)?(RB | (x23 << 1)):(x23 << 1); \ x13= (*p9 & RB)?(LB | (x23 >> 1)):(x23 >> 1); #define PROC2a(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= 0; \ x31= 0; \ x11= 0; \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1); \ x23= *p8; \ x33= (*p10 & LB)?(RB | (x23 << 1)):(x23 << 1); \ x13= (*p9 & RB)?(LB | (x23 >> 1)):(x23 >> 1); #define PROC2b(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2; \ x31= (*p4 & LB)?(RB | (x21 << 1)):(x21 << 1); \ x11= (*p3 & RB)?(LB | (x21 >> 1)):(x21 >> 1); \ x22= *p5; \ x32= (*p7 & LB)?(RB | (x22 << 1)):(x22 << 1); \ x12= (*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1); \ x23= 0; \ x33= 0; \ x13= 0; #define PROC3(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2 & c; \ x31= (x21 << 1); \ x11= ((*p3 & RB)?(LB | (x21 >> 1)):(x21 >> 1)) & c; \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= ((*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1)) & c; \ x23= *p8 & c; \ x33= (x23 << 1); \ x13= ((*p9 & RB)?(LB | (x23 >> 1)):(x23 >> 1)) & c; #define PROC3a(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= 0; \ x31= 0; \ x11= 0; \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= ((*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1)) & c; \ x23= *p8 & c; \ x33= (x23 << 1); \ x13= ((*p9 & RB)?(LB | (x23 >> 1)):(x23 >> 1)) & c; #define PROC3b(x11,x12,x13,x21,x22,x23,x31,x32,x33) \ x21= *p2 & c; \ x31= (x21 << 1); \ x11= ((*p3 & RB)?(LB | (x21 >> 1)):(x21 >> 1)) & c; \ x22= *p5 & c; \ x32= (x22 << 1); \ x12= ((*p6 & RB)?(LB | (x22 >> 1)):(x22 >> 1)) & c; \ x23= 0; \ x33= 0; \ x13= 0; #define TEST(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ d|= ~x000 & ~x001 & ~x002 & ~x010 & ~x011 & ~x012 & ~x020 & ~x021 & ~x022 & x111 & x211 \ &(x100 | x101 | x102 | x110 | x112 | x120 | x121 | x122 | x200 | x201 | x202 | x210 | x212 | x220 | x221 | x222); \ d|= ~x000 & ~x001 & ~x002 & ~x010 & ~x011 & ~x012 & x111 & x121 & x211; \ d|= ~x000 & ~x001 & ~x010 & ~x011 & x111 & x121 & x112 & x211; \ d|= ~x000 & ~x001 & ~x002 & ~x010 & ~x011 & ~x012 & ~x020 & ~x021 & x022 & x111 & x122 & x211; \ d|= ~x000 & ~x001 & ~x002 & ~x010 & ~x011 & ~x012 & ~x020 & ~x021 & ~x022 & ~x100 & ~x101 & ~x102 & ~x200 & ~x201 & ~x202 & x111 & ~x211 & x221 \ &(x110 | x112 | x120 | x121 | x122 | x210 | x212 | x220 | x222); \ d|= ~x000 & ~x001 & ~x002 & ~x010 & ~x011 & ~x012 & ~x020 & ~x021 & ~x022 & ~x100 & ~x101 & ~x110 & x111 & ~x200 & ~x201 & ~x210 & ~x211 & x212 & x221; #define TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ d= 0; \ TEST(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ TEST(x002,x012,x022,x001,x011,x021,x000,x010,x020,x102,x112,x122,x101,x111,x121,x100,x110,x120,x202,x212,x222,x201,x211,x221,x200,x210,x220) \ TEST(x022,x021,x020,x012,x011,x010,x002,x001,x000,x122,x121,x120,x112,x111,x110,x102,x101,x100,x222,x221,x220,x212,x211,x210,x202,x201,x200) \ TEST(x020,x010,x000,x021,x011,x001,x022,x012,x002,x120,x110,x100,x121,x111,x101,x122,x112,x102,x220,x210,x200,x221,x211,x201,x222,x212,x202) #define RUN(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ if (numint == 1) { \ p2= input; p5= p2; p8= p5 + numg; q2= output; \ CLEAR(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ PROC0a(b11,b12,b13,b21,b22,b23,b31,b32,b33) \ p5+= numint; p8+= numint; \ PROC0a(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d & c; \ SHIFTIT \ for (j= 2; j < height; j++) { \ p5+= numint; p8+= numint; q2+= numint; \ PROC0a(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d & c; \ SHIFTIT \ } \ q2+= numint; \ CLEAR(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ *q2= d & c; \ p5+= numint; p8+= numint; q2+= numint; \ for (k= 2; k < depth; k++){ \ CLEAR(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ PROC0(b11,b12,b13,b21,b22,b23,b31,b32,b33) \ p2+= numint; p5+= numint; p8+= numint; \ PROC0(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d & c; \ SHIFTIT \ for (j= 2; j < height; j++) { \ p2+= numint; p5+= numint; p8+= numint; q2+= numint; \ PROC0(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d & c; \ SHIFTIT \ } \ q2+= numint; \ CLEAR(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ *q2= d & c; \ p2+= numint; p5+= numint; p8+= numint; q2+= numint; \ } \ CLEAR(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ PROC0b(b11,b12,b13,b21,b22,b23,b31,b32,b33) \ p2+= numint; p5+= numint; \ PROC0b(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d & c; \ SHIFTIT \ for (j= 2; j < height; j++) { \ p2+= numint; p5+= numint; q2+= numint; \ PROC0b(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d & c; \ SHIFTIT \ } \ q2+= numint; \ CLEAR(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ *q2= d & c; \ } \ else if (numint > 1) { \ p1= input; q1= output; \ p2= p1; p5= p2; p8= p5 + numg; \ p4= p2 + 1; p7= p5 + 1; p10= p8 + 1; \ q2= q1; \ CLEAR(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ PROC1a(b11,b12,b13,b21,b22,b23,b31,b32,b33) \ p5+= numint; p8+= numint; \ p7+= numint; p10+= numint; \ PROC1a(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d; \ SHIFTIT \ for (j= 2; j < height; j++) { \ p5+= numint; p8+= numint; \ p7+= numint; p10+= numint; \ q2+= numint; \ PROC1a(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d; \ SHIFTIT \ } \ q2+= numint; \ CLEAR(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ *q2= d; \ p5+= numint; p8+= numint; \ p7+= numint; p10+= numint; \ q2+= numint; \ for (k= 2; k < depth; k++){ \ CLEAR(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ PROC1(b11,b12,b13,b21,b22,b23,b31,b32,b33) \ p2+= numint; p5+= numint; p8+= numint; \ p4+= numint; p7+= numint; p10+= numint; \ PROC1(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d; \ SHIFTIT \ for (j= 2; j < height; j++) { \ p2+= numint; p5+= numint; p8+= numint; \ p4+= numint; p7+= numint; p10+= numint; \ q2+= numint; \ PROC1(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d; \ SHIFTIT \ } \ q2+= numint; \ CLEAR(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ *q2= d; \ p2+= numint; p5+= numint; p8+= numint; \ p4+= numint; p7+= numint; p10+= numint; \ q2+= numint; \ } \ CLEAR(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ PROC1b(b11,b12,b13,b21,b22,b23,b31,b32,b33) \ p2+= numint; p5+= numint; \ p4+= numint; p7+= numint; \ PROC1b(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d; \ SHIFTIT \ for (j= 2; j < height; j++) { \ p2+= numint; p5+= numint; \ p4+= numint; p7+= numint; \ q2+= numint; \ PROC1b(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d; \ SHIFTIT \ } \ q2+= numint; \ CLEAR(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ *q2= d; \ for (i=2 ; i < numint; i++) { \ p3= p1; p6= p3; p9= p6 + numg; \ p1++; q1++; \ p2= p1; p5= p2; p8= p5 + numg; \ p4= p2 + 1; p7= p5 + 1; p10= p8 + 1; \ q2= q1; \ CLEAR(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ PROC2a(b11,b12,b13,b21,b22,b23,b31,b32,b33) \ p5+= numint; p8+= numint; \ p6+= numint; p9+= numint; \ p7+= numint; p10+= numint; \ PROC2a(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d; \ for (j= 2; j < height; j++) { \ p5+= numint; p8+= numint; \ p6+= numint; p9+= numint; \ p7+= numint; p10+= numint; \ q2+= numint; \ PROC2a(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d; \ SHIFTIT \ } \ q2+= numint; \ CLEAR(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ *q2= d; \ p5+= numint; p8+= numint; \ p6+= numint; p9+= numint; \ p7+= numint; p10+= numint; \ q2+= numint; \ for (k= 2; k < depth; k++){ \ CLEAR(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ PROC2(b11,b12,b13,b21,b22,b23,b31,b32,b33) \ p2+= numint; p5+= numint; p8+= numint; \ p3+= numint; p6+= numint; p9+= numint; \ p4+= numint; p7+= numint; p10+= numint; \ PROC2(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d; \ for (j= 2; j < height; j++) { \ p2+= numint; p5+= numint; p8+= numint; \ p3+= numint; p6+= numint; p9+= numint; \ p4+= numint; p7+= numint; p10+= numint; \ q2+= numint; \ PROC2(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d; \ SHIFTIT \ } \ q2+= numint; \ CLEAR(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ *q2= d; \ p2+= numint; p5+= numint; p8+= numint; \ p3+= numint; p6+= numint; p9+= numint; \ p4+= numint; p7+= numint; p10+= numint; \ q2+= numint; \ } \ CLEAR(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ PROC2b(b11,b12,b13,b21,b22,b23,b31,b32,b33) \ p2+= numint; p5+= numint; \ p3+= numint; p6+= numint; \ p4+= numint; p7+= numint; \ PROC2b(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d; \ for (j= 2; j < height; j++) { \ p2+= numint; p5+= numint; \ p3+= numint; p6+= numint; \ p4+= numint; p7+= numint; \ q2+= numint; \ PROC2b(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d; \ SHIFTIT \ } \ q2+= numint; \ CLEAR(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ *q2= d; \ } \ p3= p1; p6= p3; p9= p6 + numg; \ p1++; q1++; \ p2= p1; p5= p2; p8= p5 + numg; \ q2= q1; \ CLEAR(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ PROC3a(b11,b12,b13,b21,b22,b23,b31,b32,b33) \ p5+= numint; p8+= numint; \ p6+= numint; p9+= numint; \ PROC3a(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d & c; \ for (j= 2; j < height; j++) { \ p5+= numint; p8+= numint; \ p6+= numint; p9+= numint; \ q2+= numint; \ PROC3a(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d & c; \ SHIFTIT \ } \ q2+= numint; \ CLEAR(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ *q2= d & c; \ p5+= numint; p8+= numint; \ p6+= numint; p9+= numint; \ q2+= numint; \ for (k= 2; k < depth; k++){ \ CLEAR(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ PROC3(b11,b12,b13,b21,b22,b23,b31,b32,b33) \ p2+= numint; p5+= numint; p8+= numint; \ p3+= numint; p6+= numint; p9+= numint; \ PROC3(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d & c; \ for (j= 2; j < height; j++) { \ p2+= numint; p5+= numint; p8+= numint; \ p3+= numint; p6+= numint; p9+= numint; \ q2+= numint; \ PROC3(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d & c; \ SHIFTIT \ } \ q2+= numint; \ CLEAR(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ *q2= d & c; \ p2+= numint; p5+= numint; p8+= numint; \ p3+= numint; p6+= numint; p9+= numint; \ q2+= numint; \ } \ CLEAR(a11,a12,a13,a21,a22,a23,a31,a32,a33) \ PROC3b(b11,b12,b13,b21,b22,b23,b31,b32,b33) \ p2+= numint; p5+= numint; \ p3+= numint; p6+= numint; \ PROC3b(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d & c; \ for (j= 2; j < height; j++) { \ p2+= numint; p5+= numint; \ p3+= numint; p6+= numint; \ q2+= numint; \ PROC3b(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ TESTIT(x000,x001,x002,x010,x011,x012,x020,x021,x022,x100,x101,x102,x110,x111,x112,x120,x121,x122,x200,x201,x202,x210,x211,x212,x220,x221,x222) \ *q2= d & c; \ SHIFTIT \ } \ q2+= numint; \ CLEAR(c11,c12,c13,c21,c22,c23,c31,c32,c33) \ *q2= d & c; \ } INIT memset(output, 0, numint * height * depth * sizeof(size_t)); switch(dir) { case 0: RUN(a11,a12,a13,a21,a22,a23,a31,a32,a33,b11,b12,b13,b21,b22,b23,b31,b32,b33,c11,c12,c13,c21,c22,c23,c31,c32,c33) break; case 1: RUN(c11,c12,c13,c21,c22,c23,c31,c32,c33,b11,b12,b13,b21,b22,b23,b31,b32,b33,a11,a12,a13,a21,a22,a23,a31,a32,a33) break; case 2: RUN(a11,a12,a13,b11,b12,b13,c11,c12,c13,a21,a22,a23,b21,b22,b23,c21,c22,c23,a31,a32,a33,b31,b32,b33,c31,c32,c33) break; case 3: RUN(a31,a32,a33,b31,b32,b33,c31,c32,c33,a21,a22,a23,b21,b22,b23,c21,c22,c23,a11,a12,a13,b11,b12,b13,c11,c12,c13) break; case 4: RUN(a11,a21,a31,b11,b21,b31,c11,c21,c31,a12,a22,a32,b12,b22,b32,c12,c22,c32,a13,a23,a33,b13,b23,b33,c13,c23,c33) break; case 5: RUN(a13,a23,a33,b13,b23,b33,c13,c23,c33,a12,a22,a32,b12,b22,b32,c12,c22,c32,a11,a21,a31,b11,b21,b31,c11,c21,c31) break; } } #undef INIT #undef TEST #undef TESTIT #undef PROC0 #undef PROC1 #undef PROC2 #undef PROC3 #undef PROC0a #undef PROC1a #undef PROC2a #undef PROC3a #undef PROC0b #undef PROC1b #undef PROC2b #undef PROC3b #undef SHIFTIT // binary addition -4 to 3 #define ADD_BIN(I,O0,O1,O2,P,Q) \ P= I & O0; \ O0^= I; \ Q= O1 & P; \ O1^= P; \ O2^= Q; template void add2d_bin2(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { ptrdiff_t step= ((width + Numb - 1) / Numb) * height; size_t *pio= output; size_t *pio1= output + step; size_t *pio2= output + 2 * step; size_t *pib= input; size_t p, q; ptrdiff_t i; for (i= 0; i < step; i++, pib++, pio++, pio1++, pio2++) { ADD_BIN(*pib, *pio, *pio1, *pio2, p, q) } return; } //binary subtraction -4 to 3 #define SUB_BIN(I,O0,O1,O2,P,Q,S) \ P= I & O0; \ O0^= I; \ S= I ^ O1; \ Q= (P & S)|(I & O1); \ O1= (P ^ S); \ O2^= I ^ Q; template void sub2d_bin2(size_t *input, ptrdiff_t width, ptrdiff_t height, size_t *output) { ptrdiff_t step= ((width + Numb - 1) / Numb) * height; size_t *pio= output; size_t *pio1= output + step; size_t *pio2= output + 2 * step; size_t *pib= input; size_t p,q,s; ptrdiff_t i; for (i= 0; i < step; i++, pib++, pio++, pio1++, pio2++) { SUB_BIN(*pib, *pio, *pio1, *pio2, p, q, s) } return; } template void sum2d_bin2(size_t *input, ptrdiff_t width, ptrdiff_t height, char *output) { ptrdiff_t step= ((width + Numb - 1) / Numb) * height; char *pio= output; size_t *pib= input; size_t *pib1= input + step; size_t *pib2= input + 2 * step; size_t k= LB; ptrdiff_t i,j; for (i= 0; i < height; i++) { for (j= 0; j < width; j++, pio++) { if (*pib & k) (*pio)+= 1; if (*pib1 & k) (*pio)+= 2; if (*pib2 & k) (*pio)-= 4; k= k >> 1; if (k == 0) { k= LB; pib++; pib1++; pib2++; } } if (k != LB) { k= LB; pib++; pib1++; pib2++; } } return; } template void euler3d_26(size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *pom, char *buf, size_t *pom1) { ptrdiff_t step= ((width + Numb - 1) / Numb) * height * depth; memset(pom1, 0, step * 3 * sizeof(size_t)); dilate3D_0_bin(input, width, height, depth, pom); add2d_bin2(pom, width, height * depth, pom1); dilate3D_0hv_bin(input, width, height, depth, pom); sub2d_bin2(pom, width, height * depth, pom1); dilate3D_0ha_bin(input, width, height, depth, pom); sub2d_bin2(pom, width, height * depth, pom1); dilate3D_0va_bin(input, width, height, depth, pom); sub2d_bin2(pom, width, height * depth, pom1); dilate2D_0h_bin(input, width, height * depth, pom); add2d_bin2(pom, width, height * depth, pom1); dilate3D_0v_bin(input, width, height, depth, pom); add2d_bin2(pom, width, height * depth, pom1); dilate3D_0a_bin(input, width, height, depth, pom); add2d_bin2(pom, width, height * depth, pom1); sub2d_bin2(input, width, height * depth, pom1); memset(buf, 0, width * height * depth); sum2d_bin2(pom1, width, height * depth, buf); } template void simplepoints3d_26_bin(size_t *input, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, ptrdiff_t x0, ptrdiff_t y0, ptrdiff_t z0, size_t *output, char *buf1, char *buf2, size_t *bufp) { ptrdiff_t ints= (width + Numb - 1) / Numb; ptrdiff_t i, j, k, l, slize; char *p1, *p2; slize= height * width; euler3d_26(input, width, height, depth, output, buf1, bufp + ints * height * depth); memcpy(bufp, input, ints * height * depth * sizeof(size_t)); size_t punch= (PUNCH >> x0); for (i= z0; i < depth; i+= 2) for (j= y0; j < height; j+= 2) for (k= 0; k < ints; k++) bufp[(i * height + j) * ints + k]&= ~punch; euler3d_26(bufp, width, height, depth, output, buf2, bufp + ints * height * depth); //TODO num of components dN=1 memset(output, 0, ints * height * depth * sizeof(size_t)); l= (x0 < 1)?(x0 + 2):x0; for (i= 0; i < height * depth; i++) for (j= l, p1= buf1 + i * width + l, p2= buf2 + i * width + l; j < width; j+= 2, p1+= 2, p2+= 2) { *p1+= *(p1 - 1); *p2+= *(p2 - 1); } l= (y0 < 1)?(y0 + 2):y0; for (i= 0; i < depth; i++) for (j= l; j < height; j+= 2) for (k= 0, p1= buf1 + (i * height + j) * width, p2= buf2 + (i * height + j) * width; k < width; k++, p1++, p2++) { *p1+= *(p1 - width); *p2+= *(p2 - width); } l= (z0 < 1)?(z0 + 2):z0; for (i= l; i < depth; i+= 2) for (j= 0; j < height; j++) for (k= 0, p1= buf1 + (i * height + j) * width, p2= buf2 + (i * height + j) * width; k < width; k++, p1++, p2++) { *p1+= *(p1 - slize); *p2+= *(p2 - slize); } for (i= z0; i < depth; i+= 2) for (j= y0; j < height; j+= 2) for (k= x0, p1= buf1 + (i * height + j) * width + x0, p2= buf2 + (i * height + j) * width + x0; k < width; k+= 2, p1+= 2, p2+= 2) if (*p1 == *p2) output[(i * height + j) * ints + k / Numb]|= input[(i * height + j) * ints + k / Numb] & (LB >> (k % Numb)); } template void Dilate2DBin(Binary& I, int num) { ptrdiff_t i, j; size_t *q, *pdat; if (!I.data || (2 > I.nDim)) return; if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++) { if (num == 1) { memcpy(pdat, q, step * sizeof(size_t)); dilate2D_0_bin (pdat, I.dims[0], I.dims[1], q); } else for (j= 1; j < num; j++) { memcpy(pdat, q, step * sizeof(size_t)); if ((j % 3) == 2) dilate2D_8_bin (pdat, I.dims[0], I.dims[1], q); else dilate2D_4_bin (pdat, I.dims[0], I.dims[1], q); } q+= step; } delete [] pdat; return; } template void Dilate2DBin8(Binary& I) { ptrdiff_t i, j; size_t *q, *pdat; if (!I.data || (2 > I.nDim)) return; if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(size_t)); dilate2D_8_bin (pdat, I.dims[0], I.dims[1], q); q+= step; } delete [] pdat; return; } template void Erode2DBin(Binary& I, int num) { ptrdiff_t i, j; size_t *q, *pdat; if (!I.data || (2 > I.nDim)) return; if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++) { if (num == 1) { memcpy(pdat, q, step * sizeof(size_t)); erode2D_0_bin (pdat, I.dims[0], I.dims[1], q); } else for (j= 1; j < num; j++) { memcpy(pdat, q, step * sizeof(size_t)); if ((j % 3) == 2) erode2D_8_bin (pdat, I.dims[0], I.dims[1], q); else erode2D_4_bin (pdat, I.dims[0], I.dims[1], q); } q+= step; } delete [] pdat; return; } template void Erode2DBin8(Binary& I) { ptrdiff_t i, j; size_t *q, *pdat; if (!I.data || (2 > I.nDim)) return; if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(size_t)); erode2D_8_bin (pdat, I.dims[0], I.dims[1], q); q+= step; } delete [] pdat; return; } template void Boundary2DBin(Binary& I) { ptrdiff_t i; size_t *q, *pdat, *qdat; if (!I.data || (2 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1]; q= I.data; pdat= new size_t[step]; qdat= new size_t[step]; for (i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(size_t)); memcpy(qdat, q, step * sizeof(size_t)); dilate2D_0_bin (pdat, I.dims[0], I.dims[1], q); erode2D_1_bin (qdat, I.dims[0], I.dims[1], pdat); size_t *p= pdat; size_t *r= q; for (int j= 0; j < step; j++, p++, r++) *r&= ~*p; q+= step; } delete [] pdat; return; } template void Close2DBin(Binary& I, int num) { Dilate2DBin(I, num); Erode2DBin(I, num); } template void Open2DBin(Binary& I, int num) { Erode2DBin(I, num); Dilate2DBin(I, num); } template void Skeleton2DBin(Binary& I, int num= -1, con2D conn= con8) { ptrdiff_t i, j, ok, n; size_t *q, *pdat, *qdat, *rdat, *p, *pd, *qd; char *chbuf1, *chbuf2; if (!I.data || (2 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1]; ptrdiff_t size= I.dims[0] * I.dims[1]; q= I.data; pdat= new size_t[step]; qdat= new size_t[step]; rdat= new size_t[step]; chbuf1= new char[size]; chbuf2= new char[size]; for (i= 0; i < numslic; i++, q+= step) { n= 0; do { ok= 0; #define STEP(Y,X) \ if (conn==con8) simplepoints2d_8_bin(q, I.dims[0], I.dims[1], Y, X, pdat, chbuf1, chbuf2, rdat); \ else simplepoints2d_4_bin(q, I.dims[0], I.dims[1], Y, X, pdat, chbuf1, chbuf2, rdat); \ for (j= 0, p= q, pd= pdat, qd= qdat; j < step; j++, p++, pd++, qd++) { \ *pd&= ~*qd; \ ok|= *pd & *p; *p&= ~*pd; \ } if (conn==con8) endpoints2d_8_bin(q, I.dims[0], I.dims[1], qdat); else endpoints2d_4_bin(q, I.dims[0], I.dims[1], qdat); STEP(0,0) STEP(1,1) STEP(1,0) STEP(0,1) n++; } while (ok&&((num<=0)||(n void Thin2DBin(Binary& I, int num= -1, con2D conn= con8) { ptrdiff_t i, j, ok, n; size_t *q, *pdat, *qdat, *rdat, *p, *pd, *qd; char *chbuf1, *chbuf2; if (!I.data || (2 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1]; ptrdiff_t size= I.dims[0] * I.dims[1]; q= I.data; pdat= new size_t[step]; qdat= new size_t[step]; rdat= new size_t[step]; chbuf1= new char[size]; chbuf2= new char[size]; for (i= 0; i < numslic; i++, q+= step) { n= 0; do { ok= 0; #define STEP(Y,X) \ if (conn==con8) simplepoints2d_8_bin(q, I.dims[0], I.dims[1], Y, X, pdat, chbuf1, chbuf2, rdat); \ else simplepoints2d_4_bin(q, I.dims[0], I.dims[1], Y, X, pdat, chbuf1, chbuf2, rdat); \ for (j= 0, p= q, pd= pdat; j < step; j++, p++, pd++) { \ ok|= *pd & *p; *p&= ~*pd; \ } STEP(0,0) STEP(1,0) STEP(1,1) STEP(0,1) n++; if (ok&&(num<=0)) { for (j= 0, p= q, qd= qdat; j < step; j++, p++, qd++) *qd= *p; erode2D_0_bin (qdat, I.dims[0], I.dims[1], rdat); Binary pI(I); pI.data= rdat; pI.EraseEnd(); ok= 0; for (j= 0, qd= rdat; j < step; j++, qd++) ok|= (*qd != 0); } } while (ok&&((num<=0)||(n void Prune2DBin(Binary& I, int num = -1, con2D conn =con8) { ptrdiff_t i, j, ok, n; size_t *q, *pdat, *p, *pd; if (!I.data || (2 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++, q+= step) { n= 0; do { ok= 0; if (conn==con8) endpoints2d_8_bin(q, I.dims[0], I.dims[1], pdat); else endpoints2d_4_bin(q, I.dims[0], I.dims[1], pdat); for (j= 0, p= q, pd= pdat; j < step; j++, p++, pd++) { ok|= *pd & *p; *p&= ~*pd; } n++; } while (ok&&((num<=0)||(n void EndPoints2DBin(Binary& I, con2D conn =con8) { ptrdiff_t i; size_t *q, *pdat; if (!I.data || (2 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++, q+= step) { if (conn==con8) endpoints2d_8_bin(q, I.dims[0], I.dims[1], pdat); else endpoints2d_4_bin(q, I.dims[0], I.dims[1], pdat); memcpy(q, pdat, step * sizeof(size_t)); } delete [] pdat; return; } template void MidPoints2DBin(Binary& I, con2D conn =con8) { ptrdiff_t i; size_t *q, *pdat; if (!I.data || (2 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++, q+= step) { if (conn==con8) midpoints2d_8_bin(q, I.dims[0], I.dims[1], pdat); else midpoints2d_4_bin(q, I.dims[0], I.dims[1], pdat); memcpy(q, pdat, step * sizeof(size_t)); } delete [] pdat; return; } template void Dilate3DBin(Binary& I, int num) { ptrdiff_t i, j; size_t *q, *pdat; if (!I.data || (3 > I.nDim)) return; if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++) { if (num == 1) { memcpy(pdat, q, step * sizeof(size_t)); dilate3D_0_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); } else for (j= 1; j < num; j++) { memcpy(pdat, q, step * sizeof(size_t)); dilate3D_18_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); } q+= step; } delete [] pdat; return; } template void Dilate3DBin10(Binary& I) { ptrdiff_t i, j; size_t *q, *pdat; if (!I.data || (3 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(size_t)); dilate3D_10_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); q+= step; } delete [] pdat; return; } template void Dilate3DBin18(Binary& I) { ptrdiff_t i, j; size_t *q, *pdat; if (!I.data || (3 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(size_t)); dilate3D_18_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); q+= step; } delete [] pdat; return; } template void Erode3DBin(Binary& I, int num) { ptrdiff_t i, j; size_t *q, *pdat; if (!I.data || (3 > I.nDim)) return; if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++) { if (num == 1) { memcpy(pdat, q, step * sizeof(size_t)); erode3D_0_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); } else for (j= 1; j < num; j++) { memcpy(pdat, q, step * sizeof(size_t)); erode3D_18_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); } q+= step; } delete [] pdat; return; } template void Erode3DBin10(Binary& I) { ptrdiff_t i, j; size_t *q, *pdat; if (!I.data || (3 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(size_t)); erode3D_10_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); q+= step; } delete [] pdat; return; } template void Erode3DBin18(Binary& I) { ptrdiff_t i, j; size_t *q, *pdat; if (!I.data || (3 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(size_t)); erode3D_18_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); q+= step; } delete [] pdat; return; } template void Dilate3DLin_zBin(Binary& I, int num) { ptrdiff_t i, j; size_t *q, *pdat; if (!I.data || (3 > I.nDim)) return; if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++) { if (num == 1) { memcpy(pdat, q, step * sizeof(size_t)); dilate3D_0a_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); } else for (j= 1; j < num; j++) { memcpy(pdat, q, step * sizeof(size_t)); dilate3D_a_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); } q+= step; } delete [] pdat; return; } template void Erode3DLin_zBin(Binary& I, int num) { ptrdiff_t i, j; size_t *q, *pdat; if (!I.data || (3 > I.nDim)) return; if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++) { if (num == 1) { memcpy(pdat, q, step * sizeof(size_t)); erode3D_0a_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); } else for (j= 1; j < num; j++) { memcpy(pdat, q, step * sizeof(size_t)); erode3D_a_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); } q+= step; } delete [] pdat; return; } template void Boundary3DBin(Binary& I) { ptrdiff_t i; size_t *q, *pdat, *qdat; if (!I.data || (3 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; qdat= new size_t[step]; for (i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(size_t)); memcpy(qdat, q, step * sizeof(size_t)); dilate3D_0_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); erode3D_1_bin (qdat, I.dims[0], I.dims[1], I.dims[2], pdat); size_t *p= pdat; size_t *r= q; for (int j= 0; j < step; j++, p++, r++) *r&= ~*p; q+= step; } delete [] pdat; return; } template void Close3DBin(Binary& I, int num) { Dilate3DBin(I, num); Erode3DBin(I, num); } template void Open3DBin(Binary& I, int num) { Erode3DBin(I, num); Dilate3DBin(I, num); } template void Dilate2D3DBin(Binary& I, int num2, int num3) { Dilate2DBin(I, num2); Dilate3DBin(I, num3); } template void Erode2D3DBin(Binary& I, int num2, int num3) { Erode3DBin(I, num3); Erode2DBin(I, num2); } template void Close2D3DBin(Binary& I, int num2, int num3) { Dilate2DBin(I, num2); Dilate3DBin(I, num3); Erode3DBin(I, num3); Erode2DBin(I, num2); } template void Open2D3DBin(Binary& I, int num2, int num3) { Erode2DBin(I, num2); Erode3DBin(I, num3); Dilate3DBin(I, num3); Dilate2DBin(I, num2); } template void Dilate1D3DBin(Binary& I, int num2, int num3) { Dilate3DLin_zBin(I, num2); Dilate3DBin(I, num3); } template void Erode1D3DBin(Binary& I, int num2, int num3) { Erode3DBin(I, num3); Erode3DLin_zBin(I, num2); } template void Close1D3DBin(Binary& I, int num2, int num3) { Dilate3DLin_zBin(I, num2); Dilate3DBin(I, num3); Erode3DBin(I, num3); Erode3DLin_zBin(I, num2); } template void Open1D3DBin(Binary& I, int num2, int num3) { Erode3DLin_zBin(I, num2); Erode3DBin(I, num3); Dilate3DBin(I, num3); Dilate3DLin_zBin(I, num2); } template void Skeleton3DBin(Binary& I, int num= -1, con3D conn= con26) { ptrdiff_t i, j, ok, n; size_t *q, *pdat, *p, *pd; if (!I.data || (3 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++, q+= step) { n= 0; do { ok= 0; #define STEP(DIR) \ simplepointsp3d_26_bin(q, I.dims[0], I.dims[1], I.dims[2], pdat, DIR); \ for (j= 0, p= q, pd= pdat; j < step; j++, p++, pd++) { \ ok|= *pd & *p; *p&= ~*pd; \ } STEP(0) STEP(1) STEP(2) STEP(3) STEP(4) STEP(5) n++; } while (ok&&((num<=0)||(n void Skeleton3DBin(Binary& I, Binary& J, int num= -1, con3D conn= con26) { ptrdiff_t i, j, ok, n; size_t *q, *q1, *pdat, *p, *p1, *pd; if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim)) throw Dimserr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; q1= J.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++, q+= step, q1+= step) { n= 0; do { ok= 0; #define STEP(DIR) \ simplepointsp3d_26_bin(q, I.dims[0], I.dims[1], I.dims[2], pdat, DIR); \ for (j= 0, p= q, pd= pdat, p1= q1; j < step; j++, p++, pd++, p1++) { \ ok|= *pd & *p & ~*p1; *p&= ~(*pd & ~*p1); \ } STEP(0) STEP(1) STEP(2) STEP(3) STEP(4) STEP(5) n++; } while (ok&&((num<=0)||(n void Thin3DBin(Binary& I, int num= -1, con3D conn= con26) { ptrdiff_t i, j, ok, n; size_t *q, *pdat, *qdat, *rdat, *p, *pd, *qd; char *chbuf1, *chbuf2; if (!I.data || (3 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; ptrdiff_t size= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; qdat= new size_t[step]; rdat= new size_t[sizeof(size_t)*step]; chbuf1= new char[size]; chbuf2= new char[size]; for (i= 0; i < numslic; i++, q+= step) { n= 0; do { ok= 0; dilate3D_0_bin (q, I.dims[0], I.dims[1], I.dims[2], pdat); erode3D_0_bin (pdat, I.dims[0], I.dims[1], I.dims[2], q); #define STEP(Z,Y,X) \ simplepoints3d_26_bin(q, I.dims[0], I.dims[1], I.dims[2], Z, Y, X, pdat, chbuf1, chbuf2, rdat); \ for (j= 0, p= q, pd= pdat; j < step; j++, p++, pd++) { \ ok|= *pd & *p; *p&= ~*pd; \ } STEP(0,0,0) STEP(1,1,1) STEP(1,0,0) STEP(0,1,1) STEP(1,1,0) STEP(0,0,1) STEP(0,1,0) STEP(1,0,1) n++; if (ok&&(num<=0)) { for (j= 0, p= q, qd= qdat; j < step; j++, p++, qd++) *qd= *p; erode3D_0hv_bin (qdat, I.dims[0], I.dims[1], I.dims[2], rdat); Binary pI(I); pI.data= rdat; pI.EraseEnd(); ok= 0; for (j= 0, qd= rdat; j < step; j++, qd++) ok|= (*qd != 0); if (!ok) { erode3D_0ha_bin (qdat, I.dims[0], I.dims[1], I.dims[2], rdat); pI.EraseEnd(); for (j= 0, qd= rdat; j < step; j++, qd++) ok|= (*qd != 0); } if (!ok) { erode3D_0va_bin (qdat, I.dims[0], I.dims[1], I.dims[2], rdat); pI.EraseEnd(); for (j= 0, qd= rdat; j < step; j++, qd++) ok|= (*qd != 0); } } } while (ok&&((num<=0)||(n void Prune3DBin(Binary& I, int num = -1, con3D conn =con26) { ptrdiff_t i, j, ok, n; size_t *q, *pdat, *p, *pd; if (!I.data || (3 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++, q+= step) { n= 0; do { ok= 0; if (conn==con26) endpoints3d_26_bin(q, I.dims[0], I.dims[1], I.dims[2], pdat); else endpoints3d_6_bin(q, I.dims[0], I.dims[1], I.dims[2], pdat); for (j= 0, p= q, pd= pdat; j < step; j++, p++, pd++) { ok|= *pd & *p; *p&= ~*pd; } n++; } while (ok&&((num<=0)||(n void EndPoints3DBin(Binary& I, con3D conn =con26) { ptrdiff_t i; size_t *q, *pdat; if (!I.data || (3 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++, q+= step) { if (conn==con26) endpoints3d_26_bin(q, I.dims[0], I.dims[1], I.dims[2], pdat); else endpoints3d_6_bin(q, I.dims[0], I.dims[1], I.dims[2], pdat); memcpy(q, pdat, step * sizeof(size_t)); } delete [] pdat; return; } template void MidPoints3DBin(Binary& I, con3D conn =con26) { ptrdiff_t i; size_t *q, *pdat; if (!I.data || (3 > I.nDim)) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; q= I.data; pdat= new size_t[step]; for (i= 0; i < numslic; i++, q+= step) { if (conn==con26) midpoints3d_26_bin(q, I.dims[0], I.dims[1], I.dims[2], pdat); else midpoints3d_6_bin(q, I.dims[0], I.dims[1], I.dims[2], pdat); memcpy(q, pdat, step * sizeof(size_t)); } delete [] pdat; return; } //Binary drawing************************************************************************ template bool checkpoint(int nDim, double *x, double *cooar) { ptrdiff_t ok, i; double *p, *q; ok= true; q= cooar; p= x; for (i= 0; i < nDim; i++, p++, q+= 2) ok&= (*p >= *q) && (*p < *(q + 1)); return ok; } template bool clipline(int nDim, double *x1, double *x2, double *cooar) { ptrdiff_t i, k; double *p1, *p2, *q, *px1, *px2, *py1, *py2, *pp1, *pp2, r; q= cooar; p1= x1; p2= x2; for (i= 0; i < nDim; i++, p1++, p2++, q+= 2) { if (!((*p1 >= *q) && (*p1 <= *(q + 1)) && (*p2 >= *q) && (*p2 <= *(q + 1)))) { if (*p1 <= *p2) { px1= p1; px2= p2; py1= x1; py2= x2; } else { px1= p2; px2= p1; py1= x2; py2= x1; } if (*px1 < *q) { if (*px2 < *q) return false; r= (*q - *px2)/(*px1 - *px2); for (k= 0, pp1= py1, pp2= py2; k < nDim; k++, pp1++, pp2++) *pp1= *pp2 + r * (*pp1 - *pp2); *px1= *q; } if (*px2 > *(q + 1)) { if (*px1 > *(q + 1)) return false; r= (*(q + 1) - *px1)/(*px2 - *px1); for (k= 0, pp1= py1, pp2= py2; k < nDim; k++, pp1++, pp2++) *pp2= *pp1 + r * (*pp2 - *pp1); *px2= *(q + 1); } } } return true; } template void putpixel_bin(size_t *image, int nDim, ptrdiff_t *dims, double *x, double *cooar) { ptrdiff_t nints, *s, poloha, index, ok, pom, i; size_t k; double *p, *q; nints= (*dims + Numb - 1) / Numb; ok= true; q= cooar; p= x; for (i= 0; i < nDim; i++, p++, q+= 2) ok&= (*p >= *q) && (*p < *(q + 1)); if (ok) { p--; q-= 2; s= dims + (nDim - 1); poloha= 0; for (i= 1; i < nDim; i++, s--, p--, q-= 2) { pom= (ptrdiff_t)((*p - *q) / ((*(q + 1) - *q) / *s)/* + 0.5*/); index= (pom >= *s)?(*s - 1):((pom < 0)?0:pom); poloha= *s * poloha + index; } pom= (ptrdiff_t)((*p - *q)/((*(q + 1) - *q) / *s)/* + 0.5*/); index= (pom >= *s)?(*s - 1):((pom < 0)?0:pom); poloha= nints * poloha + (index / Numb); k= LB; k>>= (index % Numb); image[poloha]|= k; } } template bool getpixel_bin(size_t *image, ptrdiff_t nDim, ptrdiff_t *dims, double *x, double *cooar) { ptrdiff_t nints, *s, poloha, index, ok, pom, i; size_t k; double *p, *q; nints= (*dims + Numb - 1) / Numb; ok= true; q= cooar; p= x; for (i= 0; i < nDim; i++, p++, q+= 2) ok&= (*p >= *q) && (*p < *(q + 1)); if (ok) { p--; q-= 2; s= dims + (nDim - 1); poloha= 0; for (i= 1; i < nDim; i++, s--, p--, q-= 2) { pom= (ptrdiff_t)((*p - *q) / ((*(q + 1) - *q) / *s)/* + 0.5*/); index= (pom >= *s)?(*s - 1):((pom < 0)?0:pom); poloha= *s * poloha + index; } pom= (ptrdiff_t)((*p - *q)/((*(q + 1) - *q) / *s)/* + 0.5*/); index= (pom >= *s)?(*s - 1):((pom < 0)?0:pom); poloha= nints * poloha + (index / Numb); k= LB; k>>= (index % Numb); return (image[poloha]&k)!= 0; } return false; } template void line_bin(size_t *image, int nDim, ptrdiff_t *dims, double *x1i, double *x2i, double *cooar, bool clip) { ptrdiff_t nints, *s, poloha, index, ok, pom, i, j, maxn, isteps; size_t k; double *p1, *p2, *p, *q, *x, *dx, max, steps, pf, *x1, *x2, *r, *dc; nints= (*dims + Numb - 1) / Numb; if (((dc= (double *)malloc(nDim * sizeof(double))) == NULL) ||((x1= (double *)malloc(nDim * sizeof(double))) == NULL) ||((x2= (double *)malloc(nDim * sizeof(double))) == NULL)) { throw Memerr(); } memcpy(x1, x1i, nDim * sizeof(double)); memcpy(x2, x2i, nDim * sizeof(double)); for (i= 0; i < nDim; i++) { dc[i]= (cooar[2 * i + 1] - cooar[2 * i]) / dims[i]; } if (clip && !clipline(nDim, x1, x2, cooar)) return; for (i= 0,q= cooar,p1= x1,p2= x2,s= dims,ok= false,r=dc; i < nDim; i++,s++,p1++,p2++,q+= 2,r++) ok|= (ptrdiff_t)((*p1 - *q) / *r) != (ptrdiff_t)((*p2 - *q)/ *r); if (!ok) { putpixel_bin(image, nDim, dims, x1, cooar); free(x1); free(x2); free(dc); return; } if (((dx= (double *)malloc(nDim * sizeof(double))) == NULL) ||((x= (double *)malloc(nDim * sizeof(double))) == NULL)) { throw Memerr(); } for (i= 0; i < nDim; i++) { x[i]= x1[i] /* + 0.5*/; dx[i]= x2[i] - x1[i]; } for (i= 0,max= 0.0,maxn= 0; i < nDim; i++) if ((pf= (fabs(dx[i]) / dc[i])) > max) { max= pf; maxn= i; } steps=fabs(dx[maxn])/dc[maxn];; for (i= 0; i < nDim; i++) dx[i]/= steps; isteps= (ptrdiff_t)steps; for (j= 0; j <= isteps; j++) { q= cooar + 2 * (nDim - 1); p= x + (nDim - 1); s= dims + (nDim - 1); r= dc + (nDim - 1); poloha= 0; for (i= 1; i < nDim; i++, s--, p--, q-= 2, r--) { pom= (ptrdiff_t)((*p - *q) / *r); index= (pom >= *s)?(*s - 1):((pom < 0)?0:pom); poloha= *s * poloha + index; } pom= (ptrdiff_t)((*p - *q) / *r); index= (pom >= *s)?(*s - 1):((pom < 0)?0:pom); poloha= nints * poloha + (index / Numb); k= LB; k>>= (index % Numb); image[poloha]|= k; for (i= 0, p= x, q= dx; i < nDim; i++) *(p++)+= *(q++); } free(x); free(x1); free(x2); free(dx); free(dc); } template bool clippolygon(ObjectArray& objs, double *cooar) { ObjectArray pobjs; double bounds[4]= {cooar[0], cooar[2], - cooar[1], - cooar[3]}; ObjectArray *pob= &objs; ObjectArray *qob= &pobjs; ObjectArray *rob; int d; qob->clear(); Object os(2); for (d= 0; d < 4; d++) { if (!pob->empty()) os= *(pob->end() - 1); for (ObjectArray::iterator io = pob->begin (); io != pob->end(); io++) { if ((*io)[0] > bounds[d]) { if (os[0] <= bounds[d]) { os[0]= os[1] + (bounds[d] - os[0]) * ((*io)[1] - os[1]) / ((*io)[0] - os[0]); os[1]= - bounds[d]; qob->push_back(os); } os[1]= - (*io)[0]; os[0]= (*io)[1]; qob->push_back(os); } else if (os[0] > bounds[d]) { os[0]= os[1] + (bounds[d] - os[0]) * ((*io)[1] - os[1]) / ((*io)[0] - os[0]); os[1]= - bounds[d]; qob->push_back(os); } os= *io; } rob= pob; pob= qob; qob= rob; qob->clear(); } //TODO handle useless faces... return (objs.size() > 1); } typedef struct { ptrdiff_t y1, y2; float x, s; } EDGEG; inline bool operator<(const EDGEG a1, const EDGEG a2) { return ((a1.y1 < a2.y1)||((a1.y1 == a2.y1)&&(a1.x < a2.x)))?true:false; } inline bool predicate_a(const EDGEG *a1, const EDGEG *a2) { return (a1->x < a2->x)?true:false; } #define PUTEDGE(P1, P2) \ x1= (ptrdiff_t)(((P1)->data[0] - cooar[0]) / ((cooar[1] - cooar[0]) / dims[0])); \ y1= (ptrdiff_t)(((P1)->data[1] - cooar[2]) / ((cooar[3] - cooar[2]) / dims[1])); \ x2= (ptrdiff_t)(((P2)->data[0] - cooar[0]) / ((cooar[1] - cooar[0]) / dims[0])); \ y2= (ptrdiff_t)(((P2)->data[1] - cooar[2]) / ((cooar[3] - cooar[2]) / dims[1])); \ if (x1 < 0) x1= 0; if (x1 >= dims[0]) x1= dims[0] - 1; \ if (x2 < 0) x2= 0; if (x2 >= dims[0]) x2= dims[0] - 1; \ if (y1 < 0) y1= 0; if (y1 >= dims[1]) y1= dims[1] - 1; \ if (y2 < 0) y2= 0; if (y2 >= dims[1]) y2= dims[1] - 1; \ if (y1 != y2) { \ if (y1 < y2) { \ pg->y1= y1; \ pg->y2= y2; \ pg->x= x1; \ } \ else { \ pg->y1= y2; \ pg->y2= y1; \ pg->x= x2; \ } \ pg->s= (double)(x2 - x1)/(double)(y2 - y1); \ pg++; \ ng++; \ } template void polygondraw(size_t *image, EDGEG *eglist, EDGEG **ealist, const ptrdiff_t* dims, ptrdiff_t ng) { ptrdiff_t nints= (*dims + Numb - 1) / Numb; EDGEG *pg, **pa, **pb; ptrdiff_t na, nb; std::sort(eglist,eglist+ng); ptrdiff_t x, y, i, poloha, x1, x2, x321, x322; size_t k, l; for (y= 0, pg= eglist, na= 0; y < dims[1]; y++) { //vyhodit hrany y2=y for (i= 0, pa= ealist, pb= NULL, nb= na; i < na; i++, pa++) if (((*pa)->y2) == y) { nb--; if (pb == NULL) pb= pa; } else if (pb != NULL) { *pb= *pa; pb++; } na= nb; //aktualizovat x for (i= 0, pa= ealist; i < na; i++, pa++) (*pa)->x+= (*pa)->s; //pridat hrany y1=y pa= ealist + na; while ((ng > 0)&&(pg->y1 == y)) { *pa= pg; na++; pa++; ng--; pg++; } //sort std::sort(ealist,ealist+na,predicate_a); //kreslit for (i= 1, pa= ealist; i < na; i+= 2) { x1= (ptrdiff_t)floor((*pa)->x /* + 0.5*/); pa++; x2= (ptrdiff_t)floor((*pa)->x /* + 0.5*/) - 1; pa++; if (x2 >= x1) { x321= x1 / Numb; x322= x2 / Numb; poloha= nints * y + x321; k= AB; k>>= x1 % Numb; l= AB; l<<= Numb - 1 - (x2 % Numb); if (x321 == x322) image[poloha]|= k&l; else { image[poloha++]|= k; for (x= x321 + 1; x < x322; x++) { image[poloha++]|= AB; } image[poloha++]|= l; } } } } } template void polygonfill(size_t *image, const ptrdiff_t *dims, ObjectArray& objs, double *cooar, bool clip) { EDGEG *eglist, *pg, **ealist; ptrdiff_t x1, y1, x2, y2; ptrdiff_t ng; if ((clip && !clippolygon(objs, cooar))||!(objs.size() > 2)) return; if (((eglist= (EDGEG *)malloc((objs.size()) * sizeof(EDGEG))) == NULL)|| ((ealist= (EDGEG **)malloc((objs.size()) * sizeof(EDGEG *))) == NULL)) { printf("allocating memory\n"); return; } pg= eglist; ng= 0; for (ObjectArray::iterator io = objs.begin (); (io + 1) != objs.end(); io++) { PUTEDGE(io, io + 1); } PUTEDGE(objs.end() - 1, objs.begin()); polygondraw(image, eglist, ealist, dims, ng); free(eglist); free(ealist); } template void polygonsfill(size_t *image, ptrdiff_t *dims, ObjectArrayArray& objs, double *cooar, bool clip) { EDGEG *eglist, *pg, **ealist; ptrdiff_t i, x1, y1, x2, y2, size, ok; ptrdiff_t ng; if (!objs.size()) return; if (clip) { ok= 0; for (i= 0; i < objs.size(); i++) ok= ok || (clippolygon(objs[i], cooar)&&(objs[i].size() > 1)); if (!ok) return; } size= 0; for (i= 0; i < objs.size(); i++) size+= objs[i].size(); if (!size) return; if (((eglist= (EDGEG *)malloc((size) * sizeof(EDGEG))) == NULL)|| ((ealist= (EDGEG **)malloc((size) * sizeof(EDGEG *))) == NULL)) { printf("allocating memory\n"); return; } pg= eglist; ng= 0; for (ObjectArrayArray::iterator ioa = objs.begin (); ioa != objs.end(); ioa++) if (ioa->size() > 2) { for (ObjectArray::iterator io = ioa->begin (); (io + 1) != ioa->end(); io++) { PUTEDGE(io, io + 1); } PUTEDGE(ioa->end() - 1, ioa->begin()); } polygondraw(image, eglist, ealist, dims, ng); free(eglist); free(ealist); } #undef PUTEDGE template void trianglefill3d(size_t *image, ptrdiff_t *dims, ObjectArray& objs, double *cooar) { if (!(checkpoint(3, objs[0].data, cooar)&& checkpoint(3, objs[1].data, cooar)&& checkpoint(3, objs[2].data, cooar))) return; //min direction double ical[3]; int i; for (i= 0; i < 3; i++) ical[i]= dims[i]/(cooar[2*i+1]-cooar[2*i]); double v1[3], v2[3]; copyvect3d(objs[1].data, v1); sub3d(v1, objs[0].data); copyvect3d(objs[2].data, v2); sub3d(v2, objs[0].data); mul3d(v1, ical); mul3d(v2, ical); vec3d(v1,v2); int n=0; double min= fabs(v1[0]); for (i= 1; i < 3; i++) if (fabs(v1[i])z[in[i]]) { j= in[i]; in[i]= in[i-1]; in[i-1]= j; } if (z[in[0]]>z[in[1]]) { j= in[1]; in[1]= in[0]; in[0]= j; } int y[3]; for (i= 0; i < 3; i++) y[i]= z[in[i]]; //draw 1. if (y[0] == y[1]) line_bin(image, 3, dims, objs[in[0]].data, objs[in[1]].data, cooar, false); else { double xx1[3], xx2[3], xx3[3]; copyvect3d(objs[in[0]].data, xx1); copyvect3d(objs[in[1]].data, xx2); copyvect3d(objs[in[2]].data, xx3); for (i= y[0]; i <= y[1]; i++) { double x1[3], x2[3]; double a= double(i - y[0])/double(y[1] - y[0]); copyvect3d(xx1, x1); comb2vect3d(x1, xx2, 1.0-a, a); a= double(i - y[0])/double(y[2] - y[0]); copyvect3d(xx1, x2); comb2vect3d(x2, xx3, 1.0-a, a); line_bin(image, 3, dims, x1, x2, cooar, false); } } //draw 2. if (y[2] == y[1]) line_bin(image, 3, dims, objs[in[2]].data, objs[in[1]].data, cooar, false); else { double xx1[3], xx2[3], xx3[3]; copyvect3d(objs[in[0]].data, xx1); copyvect3d(objs[in[1]].data, xx2); copyvect3d(objs[in[2]].data, xx3); for (i= y[1]; i <= y[2]; i++) { double x1[3], x2[3]; double a= double(i - y[1])/double(y[2] - y[1]); copyvect3d(xx2, x1); comb2vect3d(x1, xx3, 1.0-a, a); a= double(i - y[0])/double(y[2] - y[0]); copyvect3d(xx1, x2); comb2vect3d(x2, xx3, 1.0-a, a); line_bin(image, 3, dims, x1, x2, cooar, false); } } } template void PointsBin(Binary& I, ObjectArray& O) { if (!I.data) throw Allocerr(); for (ObjectArray::iterator io = O.begin (); io != O.end (); io++) putpixel_bin(I.data, I.nDim, I.dims, io->data, I.bounds); } template void MaskObjects(Binary& J, ObjectArray& I, ObjectArray& O) { if (!J.data) throw Allocerr(); for (ObjectArray::iterator io = I.begin (); io != I.end (); io++) if (getpixel_bin(J.data, J.nDim, J.dims, io->data, J.bounds)) O.push_back(*io); } template void PolylineBin(Binary& I, ObjectArray& O, bool clip= true) { if (!I.data) throw Allocerr(); for (ObjectArray::iterator io = O.begin (); (io + 1) != O.end(); io++) line_bin(I.data, I.nDim, I.dims, io->data, (io + 1)->data, I.bounds, clip); } template void PolylinesBin(Binary& I, ObjectArrayArray& O, bool clip= true) { if (!I.data) throw Allocerr(); for (ObjectArrayArray::iterator io = O.begin (); io != O.end(); io++) PolylineBin(I, *io, clip); } template void SegmentsBin(Binary& I, ObjectArray& O, bool clip= true) { if (!I.data) throw Allocerr(); for (ObjectArray::iterator io = O.begin (); (io != O.end())&&((io + 1) != O.end()); io+= 2) line_bin(I.data, I.nDim, I.dims, io->data, (io + 1)->data, I.bounds, clip); } template void Polygon2DBin(Binary& I, ObjectArray& O, bool clip= true) { if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); polygonfill(I.data, I.dims, O, I.bounds, clip); } template void Polygons2DBin(Binary& I, ObjectArrayArray& O, bool clip= true) { if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); polygonsfill(I.data, I.dims, O, I.bounds, clip); } template void Triangle3DBin(Binary& I, ObjectArray& O) { if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (O.size() < 3) throw Numerr(); if ((O[0].nVar < 3)||(O[1].nVar < 3)||(O[2].nVar < 3)) throw NVarerr(); trianglefill3d(I.data, I.dims, O, I.bounds); } template void Triangles3DBin(Binary& I, ObjectArrayArray& O) { if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); for (ObjectArrayArray::iterator io = O.begin (); io != O.end(); io++) Triangle3DBin(I, *io); } //TODO cliptriangles //Measurement utilities*************************************************************************** typedef double *pdouble; template double normal(double x, double sigma) { return((double) exp( -(x*x)/(2.0*sigma*sigma))); } #define ALLOCMAT(X,M,N) \ X= new pdouble [M]; \ X[0]= new double [M * N]; \ for (i= 1; i < M; i++) \ X[i]= X[i-1] + N; #define DELETEMAT(X) \ delete[] X[0]; \ delete[] X; template void weights2D(double dx, double dy, double *wx, double *wxy, double *wy) { ptrdiff_t i, j, k; double **v, **a, b[4], p[4], x[4], d; ALLOCMAT(v,4,2) ALLOCMAT(a,4,4) d= sqrt(dx * dx + dy * dy); v[0][0]= 1.0;v[0][1]= 0.0; v[1][0]= dx / d; v[1][1]= dy / d; v[2][0]= 0.0;v[2][1]= 1.0; v[3][0]= dx / d;v[3][1]= - dy / d; for (i= 0; i < 4; i++) for (j= 0; j < 4; j++) { for (k= 0, d= 0.0; k < 2; k++) d+= v[i][k] * v[j][k]; d= fabs(d); a[i][j]= (d < 1.0)? (M_PI_2 * 0.5 * (sqrt(1.0 - d * d) + d * asin(d)) - 1.0): (M_PI_2 * M_PI_2 * 0.5 - 1.0); } DELETEMAT(v) for (i= 0; i < 4; i++) a[i][1]+= a[i][3]; for (j= 0; j < 4; j++) a[1][j]+= a[3][j]; b[0]= 1.0; b[1]= 2.0; b[2]= 1.0; choldc(a, 3, p); cholsl(a, 3, p, b, x); for (i= 0, d= 0.0; i < 3; i++) d+= x[i] * b[i]; DELETEMAT(a) *wx= x[0] / d; *wxy= x[1] / d; *wy= x[2] / d; } template void weights3D(double dx, double dy, double dz, double *wx, double *wy, double *wz, double *wxy, double *wxz, double *wyz, double *wxyz) /*optimal weights, sum of weights is 1*/ { int i, j, k; double **v, **a, b[13], p[13], x[13], d; ALLOCMAT(v,13,3) ALLOCMAT(a,13,13) v[0][0]= 1.0; v[0][1]= 0.0; v[0][2]= 0.0; v[1][0]= 0.0; v[1][1]= 1.0; v[1][2]= 0.0; v[2][0]= 0.0; v[2][1]= 0.0; v[2][2]= 1.0; d= sqrt(dx * dx + dy * dy); v[3][0]= dx / d; v[3][1]= dy / d;v[3][2]= 0.0; v[7][0]= dx / d; v[7][1]= - dy / d;v[7][2]= 0.0; d= sqrt(dx * dx + dz * dz); v[4][0]= dx / d; v[4][1]= 0.0;v[4][2]= dz / d; v[8][0]= dx / d; v[8][1]= 0.0;v[8][2]= - dz / d; d= sqrt(dy * dy + dz * dz); v[5][0]= 0.0; v[5][1]= dy / d;v[5][2]= dz / d; v[9][0]= 0.0; v[9][1]= dy / d;v[9][2]= - dz / d; d= sqrt(dx * dx + dy * dy + dz * dz); v[6][0]= dx / d; v[6][1]= dy / d;v[6][2]= dz / d; v[10][0]= dx / d; v[10][1]= dy / d;v[10][2]= - dz / d; v[11][0]= dx / d; v[11][1]= - dy / d;v[11][2]= dz / d; v[12][0]= dx / d; v[12][1]= - dy / d;v[12][2]= - dz / d; for (i= 0; i < 13; i++) for (j= 0; j < 13; j++) { for (k= 0, d= 0.0; k < 3; k++) d+= v[i][k] * v[j][k]; d= fabs(d); a[i][j]= (d < 1.0)? (4.0 / (3.0 * M_PI_2) * (sqrt(1.0 - d * d) + d * asin(d)) - 1.0): (1.0 / 3.0); } DELETEMAT(v) #define CONTR(i1,i2) \ for (i= 0; i < 13; i++) a[i][i1]+= a[i][i2]; \ for (j= 0; j < 13; j++) a[i1][j]+= a[i2][j]; CONTR(3,7) CONTR(4,8) CONTR(5,9) CONTR(6,10) CONTR(6,11) CONTR(6,12) b[0]= 1.0; b[1]= 1.0; b[2]= 1.0; b[3]= 2.0; b[4]= 2.0; b[5]= 2.0; b[6]= 4.0; choldc(a, 7, p); cholsl(a, 7, p, b, x); for (i= 0, d= 0.0; i < 7; i++) d+= b[i]*x[i]; DELETEMAT(a) *wx= x[0] / d; *wy= x[1] / d; *wz= x[2] / d; *wxy= x[3] / d; *wxz= x[4] / d; *wyz= x[5] / d; *wxyz= x[6] / d; } //Measurements************************************************************************************ template void Measure2D(Binary& I, double& Area, double& Perimeter, double& EulerNo) { size_t *p1, *p2, *p3, a, b, c, d, e, f, np, nx, ny, nxy, nyx; ptrdiff_t ne; ptrdiff_t width, height, numint, i, j; double xcal, ycal, wx, wy, wxy, xycal; if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); width= I.dims[0]; height= I.dims[1]; xcal= I.Dx(0); ycal= I.Dx(1); numint= (width + Numb - 1) / Numb; c= ((width % Numb) == 0)?(AB):(AB << (Numb - (width % Numb))); d= c << 1; np= 0; nx= 0; ny= 0; nxy= 0; nyx= 0; ne= 0; weights2D(xcal, ycal, &wx, &wxy, &wy); if (numint > 0) { p1= I.data; for (i= 1; i < numint; i++) { p3= p1 + 1; p2= p1; e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); np+= bitnum(e); nx+= bitnum(e ^ f); for (j= 1; j < height; j++) { p2+= numint; p3+= numint; a= e; b= f; e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); np+= bitnum(e); nx+= bitnum(e ^ f); ny+= bitnum(a ^ e); nxy+= bitnum(a ^ f); nyx+= bitnum(b ^ e); ne+= 2 * (bitnum(a & ~e & ~f) - bitnum(a & b & ~f) + bitnum(b & ~e & ~f) - bitnum(a & b & ~e)); } p1++; } p3= p1 + 1; p2= p1; e= *p2 & c; f= e << 1; np+= bitnum(e); nx+= bitnum((e ^ f) & d); for (j= 1; j < height; j++) { p2+= numint; p3+= numint; a= e; b= f; e= *p2 & c; f= e << 1; np+= bitnum(e); ny+= bitnum(a ^ e); nx+= bitnum((e ^ f) & d); nxy+= bitnum((a ^ f) & d); nyx+= bitnum((b ^ e) & d); ne+= 2 * (bitnum((a & ~e & ~f) & d) - bitnum((a & b & ~f) & d) + bitnum((b & ~e & ~f) & d) - bitnum((a & b & ~e) & d)); } p1= I.data; for (i=1 ; i < numint; i++) { p3= p1 + 1; e= *p1; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); ne-= bitnum(e ^ f); p1++; } e= *p1 & c; f= e << 1; ne-= bitnum((e ^ f) & d); p1= I.data + (height - 1) * numint; for (i=1 ; i < numint; i++) { p3= p1 + 1; e= *p1; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); ne+= bitnum(e ^ f); p1++; } e= *p1 & c; f= e << 1; ne+= bitnum((e ^ f) & d); } Area= xcal * ycal * np; xycal= xcal * ycal / sqrt( xcal * xcal + ycal * ycal); Perimeter= M_PI_2 * (wx * ycal * nx + wy * xcal * ny + wxy * xycal * (nxy + nyx)); EulerNo= 0.25 * ne; } template void Euler2D (Binary& I, double& EulerNo4, double& EulerNo6, double& EulerNo8) { size_t *p1, *p2, *p3, a, b, c, d, e, f; ptrdiff_t ne4, ne6, ne8; ptrdiff_t width, height, numint, i, j; if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); width= I.dims[0]; height= I.dims[1]; numint= (width + Numb - 1) / Numb; c= ((width % Numb) == 0)?(AB):(AB << (Numb - (width % Numb))); d= c << 1; ne4= 0; ne6= 0; ne8= 0; if (numint > 0) { p1= I.data; for (i= 1; i < numint; i++) { p3= p1 + 1; p2= p1; e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); for (j= 1; j < height; j++) { p2+= numint; p3+= numint; a= e; b= f; e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); ne6+= 2 * (bitnum(a & ~e & ~f) - bitnum(a & b & ~f) + bitnum(b & ~e & ~f) - bitnum(a & b & ~e)); ne4+= bitnum(a) - bitnum(a & b) - bitnum(a & e) + bitnum(a & b & e & f); ne8+= bitnum(a | b | e | f) - bitnum(a | b) - bitnum(a | e) + bitnum(a); } p1++; } p3= p1 + 1; p2= p1; e= *p2 & c; f= e << 1; for (j= 1; j < height; j++) { p2+= numint; p3+= numint; a= e; b= f; e= *p2 & c; f= e << 1; ne6+= 2 * (bitnum((a & ~e & ~f) & d) - bitnum((a & b & ~f) & d) + bitnum((b & ~e & ~f) & d) - bitnum((a & b & ~e) & d)); ne4+= bitnum(a & d) - bitnum((a & b) & d) - bitnum((a & e) & d) + bitnum((a & b & e & f) & d); ne8+= bitnum((a | b | e | f) & d) - bitnum((a | b) & d) - bitnum((a | e) & d) + bitnum(a & d); } p1= I.data; for (i=1 ; i < numint; i++) { p3= p1 + 1; e= *p1; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); ne6-= bitnum(e ^ f); p1++; } e= *p1 & c; f= e << 1; ne6-= bitnum((e ^ f) & d); p1= I.data + (height - 1) * numint; for (i=1 ; i < numint; i++) { p3= p1 + 1; e= *p1; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); ne6+= bitnum(e ^ f); p1++; } e= *p1 & c; f= e << 1; ne6+= bitnum((e ^ f) & d); } EulerNo4= ne4; EulerNo6= 0.25 * ne6; EulerNo8= ne8; } template void Measure3D(Binary& I, double& Volume, double& Surface, double& Length, double& EulerNo) { //Euler 0.5(E6+E26) //TODO: okr. efekty L, E (zbyva anizotropie) size_t *p1, *p2, *p3, *p5, *p6, a, b, c, d, e, f, g, h, ae, bf, cg, dh, msk, ms; size_t nvox, nx, ny, nz, nxy, nxz, nyz, nx_y, nx_z, ny_z, nxyz, nxy_z, nx_yz, nx_y_z; ptrdiff_t nex, ney, nez, nexy, nexz, neyz, nex_y, nex_z, ney_z, nexyz, nexy_z, nex_yz, nex_y_z, ne; ptrdiff_t numint, numg, i, j, k; double sx, sy, sz, sxy, sxz, syz, sxyz, dx, dy, dz, dxy, dxz, dyz, dxyz, wx, wy, wz, wxy, wxz, wyz, wxyz, ax, ay, az, axy, axz, ayz, ax_y, ax_z, ay_z, axyz, axy_z, ax_yz, ax_y_z, lx, ly, lz, lxy, lxz, lyz, lx_y, lx_z, ly_z, lxyz, lxy_z, lx_yz, lx_y_z; ptrdiff_t width= I.dims[0]; ptrdiff_t height= I.dims[1]; ptrdiff_t depth= I.dims[2]; double xcal = I.Dx(0); double ycal = I.Dx(1); double zcal = I.Dx(2); numint= (width + Numb - 1) / Numb; numg= numint * height; msk= ((width % Numb) == 0)?(AB):(AB << (Numb - (width % Numb))); ms= msk << 1; nvox= 0; nx= 0; ny= 0; nz= 0; nxy= 0; nxz= 0; nyz= 0; nx_y= 0; nx_z= 0; ny_z= 0; nxyz= 0; nxy_z= 0; nx_yz= 0; nx_y_z= 0; nex= 0; ney= 0; nez= 0; nexy= 0; nexz= 0; neyz= 0; nex_y= 0; nex_z= 0; ney_z= 0; nexyz= 0; nexy_z= 0; nex_yz= 0; nex_y_z= 0; ne= 0; #define EINCR(N,A,B,C,D) \ N+= bitnum(A & ~C & ~D) - bitnum(A & B & ~D) + bitnum(B & ~C & ~D) - bitnum(A & B & ~C); if (numint > 0) { p1= I.data; for (i=1 ; i < numint; i++) { p3= p1 + 1; p6= p3 + numg; p2= p1; p5= p2 + numg; for (k= 1; k < depth; k++){ e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); g= *p5; h= (*p6 & LB)?(RB | (g << 1)):(g << 1); nvox+= bitnum(e); nx+= bitnum(e ^ f); nz+= bitnum(e ^ g); nxz+= bitnum(e ^ h); nx_z+= bitnum(f ^ g ); EINCR(ney,e,f,g,h); for (j= 1; j < height; j++) { p2+= numint; p5+= numint; p3+= numint; p6+= numint; a= e; b= f; c= g; d= h; e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); g= *p5; h= (*p6 & LB)?(RB | (g << 1)):(g << 1); nvox+= bitnum(e); nx+= bitnum(e ^ f); ny+= bitnum(e ^ a); nz+= bitnum(e ^ g); nx_y+= bitnum(e ^ b); nxy+= bitnum(f ^ a); ny_z+= bitnum(e ^ c); nyz+= bitnum(a ^ g); nxz+= bitnum(e ^ h); nx_z+= bitnum(f ^ g ); nx_yz+= bitnum(e ^ d); nxy_z+= bitnum(f ^ c); nxyz+= bitnum(a ^ h); nx_y_z+= bitnum(b ^ g); EINCR(nex,a,c,e,g); EINCR(ney,e,f,g,h); EINCR(nez,a,b,e,f); EINCR(nex_y,a,c,f,h); EINCR(nexy,b,d,e,g); EINCR(nex_z,a,d,e,h); EINCR(nexz,c,b,g,f); EINCR(ney_z,a,b,g,h); EINCR(neyz,c,d,e,f); nex_y_z+= bitnum(~a & ~d & f) - bitnum(~c & e & h); nexyz+= bitnum(~c & ~b & e) - bitnum(~d & g & f); nexy_z+= bitnum(~a & ~d & g) - bitnum(~b & e & h); nex_yz+= bitnum(~c & ~b & h) - bitnum(~a & g & f); /* ae= a & e; bf= b & f; cg= c & g; ne+= bitnum(e & ~f & ~g) - bitnum(e & f & g & ~h) - bitnum(ae & ~bf & ~cg) + bitnum(ae & bf & cg & ~(d & h)); bf= b | f; cg= c | g; dh= d | h; ne+= bitnum((a | e) & ~bf & ~cg & ~dh) - bitnum(bf & cg & ~dh) - bitnum(e & ~f & ~g & ~h) + bitnum(f & g & ~h); */ ne+= /*bitnum(a)*/ - bitnum(a & b) - bitnum(a & c) - bitnum(a & e) + bitnum(a & b & c & d) + bitnum(a & b & e & f) + bitnum(a & e & c & g) - bitnum(a & b & c & d & e & f & g & h); ne-= /*bitnum(a)*/ - bitnum(a | b) - bitnum(a | c) - bitnum(a | e) + bitnum(a | b | c | d) + bitnum(a | b | e | f) + bitnum(a | e | c | g) - bitnum(a | b | c | d | e | f | g | h); } p2+= numint; p5+= numint; p3+= numint; p6+= numint; } e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); nvox+= bitnum(e); nx+= bitnum(e ^ f); for (j= 1; j < height; j++) { p2+= numint; p5+= numint; p3+= numint; p6+= numint; a= e; b= f; e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); nvox+= bitnum(e); nx+= bitnum(e ^ f); ny+= bitnum(e ^ a); nx_y+= bitnum(e ^ b); nxy+= bitnum(f ^ a); EINCR(nez,a,b,e,f); } p1++; } #undef EINCR #define EINCRM(N,A,B,C,D,M) \ N+= bitnum((A & ~C & ~D) & M) - bitnum((A & B & ~D) & M) \ + bitnum((B & ~C & ~D) & M) - bitnum((A & B & ~C) & M); p2= p1; p5= p2 + numg; for (k= 1; k < depth; k++){ e= *p2 & msk; f= e << 1; g= *p5 & msk; h= g << 1; nvox+= bitnum(e); nx+= bitnum((e ^ f) & ms); nz+= bitnum(e ^ g); nxz+= bitnum((e ^ h) & ms); nx_z+= bitnum((f ^ g) & ms); EINCRM(ney,e,f,g,h,ms); for (j= 1; j < height; j++) { p2+= numint; p5+= numint; a= e; b= f; c= g; d= h; e= *p2 & msk; f= e << 1; g= *p5 & msk; h= g << 1; nvox+= bitnum(e); nx+= bitnum((e ^ f) & ms); ny+= bitnum(e ^ a); nz+= bitnum(e ^ g); nx_y+= bitnum((e ^ b) & ms); nxy+= bitnum((f ^ a) & ms); ny_z+= bitnum(e ^ c); nyz+= bitnum(a ^ g); nxz+= bitnum((e ^ h) & ms); nx_z+= bitnum((f ^ g) & ms); nx_yz+= bitnum((e ^ d) & ms); nxy_z+= bitnum((f ^ c) & ms); nxyz+= bitnum((a ^ h) & ms); nx_y_z+= bitnum((b ^ g) & ms); EINCRM(nex,a,c,e,g,msk); EINCRM(ney,e,f,g,h,ms); EINCRM(nez,a,b,e,f,ms); EINCRM(nex_y,a,c,f,h,ms); EINCRM(nexy,b,d,e,g,ms); EINCRM(nex_z,a,d,e,h,ms); EINCRM(nexz,c,b,g,f,ms); EINCRM(ney_z,a,b,g,h,ms); EINCRM(neyz,c,d,e,f,ms); nex_y_z+= bitnum((~a & ~d & f) & ms) - bitnum((~c & e & h) & ms); nexyz+= bitnum((~c & ~b & e) & ms) - bitnum((~d & g & f) & ms); nexy_z+= bitnum((~a & ~d & g) & ms) - bitnum((~b & e & h) & ms); nex_yz+= bitnum((~c & ~b & h) & ms) - bitnum((~a & g & f) & ms); /* ae= a & e; bf= b & f; cg= c & g; ne+= bitnum((e & ~f & ~g) & ms) - bitnum((e & f & g & ~h) & ms) - bitnum((ae & ~bf & ~cg) & ms) + bitnum((ae & bf & cg & ~(d & h)) & ms); bf= b | f; cg= c | g; dh= d | h; ne+= bitnum(((a | e) & ~bf & ~cg & ~dh) & ms) - bitnum((bf & cg & ~dh) & ms) - bitnum((e & ~f & ~g & ~h) & ms) + bitnum((f & g & ~h) & ms); */ ne+= /*bitnum(a & ms)*/ - bitnum((a & b) & ms) - bitnum((a & c) & ms) - bitnum((a & e) & ms) + bitnum((a & b & c & d) & ms) + bitnum((a & b & e & f) & ms) + bitnum((a & e & c & g) & ms) - bitnum((a & b & c & d & e & f & g & h) & ms); ne-= /*bitnum(a & ms)*/ - bitnum((a | b) & ms) - bitnum((a | c) & ms) - bitnum((a | e) & ms) + bitnum((a | b | c | d) & ms) + bitnum((a | b | e | f) & ms) + bitnum((a | e | c | g) & ms) - bitnum((a | b | c | d | e | f | g | h) & ms); } p2+= numint; p5+= numint; } e= *p2 & msk; f= e << 1; nvox+= bitnum(e); nx+= bitnum((e ^ f) & ms); for (j= 1; j < height; j++) { p2+= numint; p5+= numint; a= e; b= f; e= *p2 & msk; f= e << 1; nvox+= bitnum(e); nx+= bitnum((e ^ f) & ms); ny+= bitnum(e ^ a); nx_y+= bitnum((e ^ b) & ms); nxy+= bitnum((f ^ a) & ms); EINCRM(nez,a,b,e,f,ms); } } #undef EINCRM Volume= xcal * ycal * zcal * nvox; sx= ycal * zcal; sy= xcal * zcal; sz= xcal * ycal; sxy= zcal * xcal * ycal / sqrt( xcal * xcal + ycal * ycal); sxz= zcal * xcal * ycal / sqrt( xcal * xcal + zcal * zcal); syz= zcal * xcal * ycal / sqrt( ycal * ycal + zcal * zcal); sxyz= zcal * xcal * ycal / sqrt( xcal * xcal + ycal * ycal + zcal * zcal); ax= 2.0 * sx * nx; ay= 2.0 * sy * ny; az= 2.0 * sz * nz; axy= 2.0 * sxy * nxy; axz= 2.0 * sxz * nxz; ayz= 2.0 * syz * nyz; ax_y= 2.0 * sxy * nx_y; ax_z= 2.0 * sxz * nx_z; ay_z= 2.0 * syz * ny_z; axyz= 2.0 * sxyz * nxyz; axy_z= 2.0 * sxyz * nxy_z; ax_yz= 2.0 * sxyz * nx_yz; ax_y_z= 2.0 * sxyz * nx_y_z; weights3D(xcal, ycal, zcal, &wx, &wy, &wz, &wxy, &wxz, &wyz, &wxyz); Surface= wx * ax + wy * ay + wz * az + wxy * (axy + ax_y) + wxz * (axz + ax_z) + wyz * (ayz + ay_z) + wxyz * (axyz + axy_z + ax_yz + ax_y_z); dx= xcal; dy= ycal; dz= zcal; dxy= xcal * ycal / sqrt( xcal * xcal + ycal * ycal); dxz= xcal * zcal / sqrt( xcal * xcal + zcal * zcal); dyz= ycal * zcal / sqrt( ycal * ycal + zcal * zcal); dxyz= xcal * ycal * zcal / sqrt( xcal * xcal * ycal * ycal + ycal * ycal * zcal * zcal + xcal * xcal * zcal * zcal); lx= dx * nex; ly= dy * ney; lz= dz * nez; lxy= dxy * nexy; lx_y= dxy * nex_y; lxz= dxz * nexz; lx_z= dxz * nex_z; lyz= dyz * neyz; ly_z= dyz * ney_z; lxyz= 2.0 * dxyz * nexyz; lxy_z= 2.0 * dxyz * nexy_z; lx_yz= 2.0 * dxyz * nex_yz; lx_y_z= 2.0 * dxyz * nex_y_z; weights3D(1.0 / xcal, 1.0 / ycal, 1.0 / zcal, &wx, &wy, &wz, &wxy, &wxz, &wyz, &wxyz); Length= wx * lx + wy * ly + wz * lz + wxy * (lxy + lx_y) + wxz * (lxz + lx_z) + wyz * (lyz + ly_z) + wxyz * (lxyz + lxy_z + lx_yz + lx_y_z); EulerNo= 0.5 * ne; } template void Measure3D3(Binary& I, double& Volume, double& Surface, double& Length, double& EulerNo, float* rosea = NULL, float* rosel = NULL) { //Euler 0.5(E6+E26) //TODO: okr. efekty E (zbyva anizotropie) size_t *p1, *p2, *p3, *p5, *p6, a, b, c, d, e, f, g, h, ae, bf, cg, dh, msk, ms, mk; size_t nvox, nx, ny, nz, nxy, nxz, nyz, nx_y, nx_z, ny_z, nxyz, nxy_z, nx_yz, nx_y_z; ptrdiff_t nex, ney, nez, nexy, nexz, neyz, nex_y, nex_z, ney_z, nexyz, nexy_z, nex_yz, nex_y_z, ne; ptrdiff_t numint, numg, i, j, k; double sx, sy, sz, sxy, sxz, syz, sxyz, dx, dy, dz, dxy, dxz, dyz, dxyz, wx, wy, wz, wxy, wxz, wyz, wxyz, ax, ay, az, axy, axz, ayz, ax_y, ax_z, ay_z, axyz, axy_z, ax_yz, ax_y_z, lx, ly, lz, lxy, lxz, lyz, lx_y, lx_z, ly_z, lxyz, lxy_z, lx_yz, lx_y_z; ptrdiff_t width= I.dims[0]; ptrdiff_t height= I.dims[1]; ptrdiff_t depth= I.dims[2]; double xcal = I.Dx(0); double ycal = I.Dx(1); double zcal = I.Dx(2); numint= (width + Numb - 1) / Numb; numg= numint * height; msk= ((width % Numb) == 0)?(AB):(AB << (Numb - (width % Numb))); ms= msk << 1; mk= msk ^ ms; nvox= 0; nx= 0; ny= 0; nz= 0; nxy= 0; nxz= 0; nyz= 0; nx_y= 0; nx_z= 0; ny_z= 0; nxyz= 0; nxy_z= 0; nx_yz= 0; nx_y_z= 0; nex= 0; ney= 0; nez= 0; nexy= 0; nexz= 0; neyz= 0; nex_y= 0; nex_z= 0; ney_z= 0; nexyz= 0; nexy_z= 0; nex_yz= 0; nex_y_z= 0; ne= 0; #define EINCR(N,A,B,C,D) \ N+= 2 * (bitnum(A & ~C & ~D) - bitnum(A & B & ~D) + bitnum(B & ~C & ~D) - bitnum(A & B & ~C)); if (numint > 0) { p1= I.data; for (i=1 ; i < numint; i++) { p3= p1 + 1; p2= p1; for (j= 0; j < height; j++) { e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); ney-= bitnum(e ^ f); p2+= numint; p3+= numint; } p3= p1 + 1; p6= p3 + numg; p2= p1; p5= p2 + numg; for (k= 1; k < depth; k++){ e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); g= *p5; h= (*p6 & LB)?(RB | (g << 1)):(g << 1); nvox+= bitnum(e); nx+= bitnum(e ^ f); nz+= bitnum(e ^ g); nxz+= bitnum(e ^ h); nx_z+= bitnum(f ^ g ); EINCR(ney,e,f,g,h); nez-= bitnum(e ^ f); nex-= bitnum(e ^ g); for (j= 1; j < height; j++) { p2+= numint; p5+= numint; p3+= numint; p6+= numint; a= e; b= f; c= g; d= h; e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); g= *p5; h= (*p6 & LB)?(RB | (g << 1)):(g << 1); nvox+= bitnum(e); nx+= bitnum(e ^ f); ny+= bitnum(e ^ a); nz+= bitnum(e ^ g); nx_y+= bitnum(e ^ b); nxy+= bitnum(f ^ a); ny_z+= bitnum(e ^ c); nyz+= bitnum(a ^ g); nxz+= bitnum(e ^ h); nx_z+= bitnum(f ^ g ); nx_yz+= bitnum(e ^ d); nxy_z+= bitnum(f ^ c); nxyz+= bitnum(a ^ h); nx_y_z+= bitnum(b ^ g); EINCR(nex,a,c,e,g); EINCR(ney,e,f,g,h); EINCR(nez,a,b,e,f); /* EINCR(nex_y,a,c,f,h); EINCR(nexy,b,d,e,g); EINCR(nex_z,a,d,e,h); EINCR(nexz,c,b,g,f); EINCR(ney_z,a,b,g,h); EINCR(neyz,c,d,e,f); nex_y_z+= bitnum(~a & ~d & f) - bitnum(~c & e & h); nexyz+= bitnum(~c & ~b & e) - bitnum(~d & g & f); nexy_z+= bitnum(~a & ~d & g) - bitnum(~b & e & h); nex_yz+= bitnum(~c & ~b & h) - bitnum(~a & g & f); */ /* ae= a & e; bf= b & f; cg= c & g; ne+= bitnum(e & ~f & ~g) - bitnum(e & f & g & ~h) - bitnum(ae & ~bf & ~cg) + bitnum(ae & bf & cg & ~(d & h)); bf= b | f; cg= c | g; dh= d | h; ne+= bitnum((a | e) & ~bf & ~cg & ~dh) - bitnum(bf & cg & ~dh) - bitnum(e & ~f & ~g & ~h) + bitnum(f & g & ~h); */ ne+= /*bitnum(a)*/ - bitnum(a & b) - bitnum(a & c) - bitnum(a & e) + bitnum(a & b & c & d) + bitnum(a & b & e & f) + bitnum(a & e & c & g) - bitnum(a & b & c & d & e & f & g & h); ne-= /*bitnum(a)*/ - bitnum(a | b) - bitnum(a | c) - bitnum(a | e) + bitnum(a | b | c | d) + bitnum(a | b | e | f) + bitnum(a | e | c | g) - bitnum(a | b | c | d | e | f | g | h); } nez+= bitnum(e ^ f); nex+= bitnum(e ^ g); p2+= numint; p5+= numint; p3+= numint; p6+= numint; } e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); nvox+= bitnum(e); nx+= bitnum(e ^ f); nez-= bitnum(e ^ f); ney+= bitnum(e ^ f); for (j= 1; j < height; j++) { p2+= numint; p3+= numint; a= e; b= f; e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); nvox+= bitnum(e); nx+= bitnum(e ^ f); ny+= bitnum(e ^ a); nx_y+= bitnum(e ^ b); nxy+= bitnum(f ^ a); EINCR(nez,a,b,e,f); ney+= bitnum(e ^ f); } nez+= bitnum(e ^ f); p1++; } #undef EINCR #define EINCRM(N,A,B,C,D,M) \ N+= 2 * (bitnum((A & ~C & ~D) & M) - bitnum((A & B & ~D) & M) \ + bitnum((B & ~C & ~D) & M) - bitnum((A & B & ~C) & M)); p2= p1; for (j= 0; j < height; j++) { e= *p2 & msk; f= e << 1; ney-= bitnum((e ^ f) & ms); p2+= numint; } p2= p1; p5= p2 + numg; for (k= 1; k < depth; k++){ e= *p2 & msk; f= e << 1; g= *p5 & msk; h= g << 1; nvox+= bitnum(e); nx+= bitnum((e ^ f) & ms); nz+= bitnum(e ^ g); nxz+= bitnum((e ^ h) & ms); nx_z+= bitnum((f ^ g) & ms); EINCRM(ney,e,f,g,h,ms); nez-= bitnum((e ^ f) & ms); nex-= bitnum(e ^ g); for (j= 1; j < height; j++) { p2+= numint; p5+= numint; a= e; b= f; c= g; d= h; e= *p2 & msk; f= e << 1; g= *p5 & msk; h= g << 1; nvox+= bitnum(e); nx+= bitnum((e ^ f) & ms); ny+= bitnum(e ^ a); nz+= bitnum(e ^ g); nx_y+= bitnum((e ^ b) & ms); nxy+= bitnum((f ^ a) & ms); ny_z+= bitnum(e ^ c); nyz+= bitnum(a ^ g); nxz+= bitnum((e ^ h) & ms); nx_z+= bitnum((f ^ g) & ms); nx_yz+= bitnum((e ^ d) & ms); nxy_z+= bitnum((f ^ c) & ms); nxyz+= bitnum((a ^ h) & ms); nx_y_z+= bitnum((b ^ g) & ms); EINCRM(nex,a,c,e,g,msk); EINCRM(ney,e,f,g,h,ms); EINCRM(nez,a,b,e,f,ms); /* EINCRM(nex_y,a,c,f,h,ms); EINCRM(nexy,b,d,e,g,ms); EINCRM(nex_z,a,d,e,h,ms); EINCRM(nexz,c,b,g,f,ms); EINCRM(ney_z,a,b,g,h,ms); EINCRM(neyz,c,d,e,f,ms); nex_y_z+= bitnum((~a & ~d & f) & ms) - bitnum((~c & e & h) & ms); nexyz+= bitnum((~c & ~b & e) & ms) - bitnum((~d & g & f) & ms); nexy_z+= bitnum((~a & ~d & g) & ms) - bitnum((~b & e & h) & ms); nex_yz+= bitnum((~c & ~b & h) & ms) - bitnum((~a & g & f) & ms); */ /* ae= a & e; bf= b & f; cg= c & g; ne+= bitnum((e & ~f & ~g) & ms) - bitnum((e & f & g & ~h) & ms) - bitnum((ae & ~bf & ~cg) & ms) + bitnum((ae & bf & cg & ~(d & h)) & ms); bf= b | f; cg= c | g; dh= d | h; ne+= bitnum(((a | e) & ~bf & ~cg & ~dh) & ms) - bitnum((bf & cg & ~dh) & ms) - bitnum((e & ~f & ~g & ~h) & ms) + bitnum((f & g & ~h) & ms); */ ne+= /*bitnum(a & ms)*/ - bitnum((a & b) & ms) - bitnum((a & c) & ms) - bitnum((a & e) & ms) + bitnum((a & b & c & d) & ms) + bitnum((a & b & e & f) & ms) + bitnum((a & e & c & g) & ms) - bitnum((a & b & c & d & e & f & g & h) & ms); ne-= /*bitnum(a & ms)*/ - bitnum((a | b) & ms) - bitnum((a | c) & ms) - bitnum((a | e) & ms) + bitnum((a | b | c | d) & ms) + bitnum((a | b | e | f) & ms) + bitnum((a | e | c | g) & ms) - bitnum((a | b | c | d | e | f | g | h) & ms); } nez+= bitnum((e ^ f) & ms); nex+= bitnum(e ^ g); p2+= numint; p5+= numint; } e= *p2 & msk; f= e << 1; nvox+= bitnum(e); nx+= bitnum((e ^ f) & ms); nez-= bitnum((e ^ f) & ms); ney+= bitnum((e ^ f) & ms); for (j= 1; j < height; j++) { p2+= numint; a= e; b= f; e= *p2 & msk; f= e << 1; nvox+= bitnum(e); nx+= bitnum((e ^ f) & ms); ny+= bitnum(e ^ a); nx_y+= bitnum((e ^ b) & ms); nxy+= bitnum((f ^ a) & ms); EINCRM(nez,a,b,e,f,ms); ney+= bitnum((e ^ f) & ms); } nez+= bitnum((e ^ f) & ms); } #undef EINCRM Volume= xcal * ycal * zcal * nvox; sx= ycal * zcal; sy= xcal * zcal; sz= xcal * ycal; sxy= zcal * xcal * ycal / sqrt( xcal * xcal + ycal * ycal); sxz= zcal * xcal * ycal / sqrt( xcal * xcal + zcal * zcal); syz= zcal * xcal * ycal / sqrt( ycal * ycal + zcal * zcal); sxyz= zcal * xcal * ycal / sqrt( xcal * xcal + ycal * ycal + zcal * zcal); ax= 2.0 * sx * nx; ay= 2.0 * sy * ny; az= 2.0 * sz * nz; axy= 2.0 * sxy * nxy; axz= 2.0 * sxz * nxz; ayz= 2.0 * syz * nyz; ax_y= 2.0 * sxy * nx_y; ax_z= 2.0 * sxz * nx_z; ay_z= 2.0 * syz * ny_z; axyz= 2.0 * sxyz * nxyz; axy_z= 2.0 * sxyz * nxy_z; ax_yz= 2.0 * sxyz * nx_yz; ax_y_z= 2.0 * sxyz * nx_y_z; weights3D(xcal, ycal, zcal, &wx, &wy, &wz, &wxy, &wxz, &wyz, &wxyz); Surface= wx * ax + wy * ay + wz * az + wxy * (axy + ax_y) + wxz * (axz + ax_z) + wyz * (ayz + ay_z) + wxyz * (axyz + axy_z + ax_yz + ax_y_z); if (rosea) { rosea[0]= wx; rosea[1]= ax / Surface; rosea[2]= wy; rosea[3]= ay / Surface; rosea[4]= wz; rosea[5]= az / Surface; rosea[6]= wxy; rosea[7]= axy / Surface; rosea[8]= wxy; rosea[9]= ax_y / Surface; rosea[10]= wxz; rosea[11]= axz / Surface; rosea[12]= wxz; rosea[13]= ax_z / Surface; rosea[14]= wyz; rosea[15]= ayz / Surface; rosea[16]= wyz; rosea[17]= ay_z / Surface; rosea[18]= wxyz; rosea[19]= axyz / Surface; rosea[20]= wxyz; rosea[21]= axy_z / Surface; rosea[22]= wxyz; rosea[23]= ax_yz / Surface; rosea[24]= wxyz; rosea[25]= ax_y_z / Surface; } dx= xcal; dy= ycal; dz= zcal; dxy= xcal * ycal / sqrt( xcal * xcal + ycal * ycal); dxz= xcal * zcal / sqrt( xcal * xcal + zcal * zcal); dyz= ycal * zcal / sqrt( ycal * ycal + zcal * zcal); dxyz= xcal * ycal * zcal / sqrt( xcal * xcal * ycal * ycal + ycal * ycal * zcal * zcal + xcal * xcal * zcal * zcal); lx= 0.5 * dx * nex; ly= 0.5 * dy * ney; lz= 0.5 * dz * nez; /* lx= dx * nex; ly= dy * ney; lz= dz * nez; lxy= dxy * nexy; lx_y= dxy * nex_y; lxz= dxz * nexz; lx_z= dxz * nex_z; lyz= dyz * neyz; ly_z= dyz * ney_z; lxyz= 2.0 * dxyz * nexyz; lxy_z= 2.0 * dxyz * nexy_z; lx_yz= 2.0 * dxyz * nex_yz; lx_y_z= 2.0 * dxyz * nex_y_z; weights3D(1.0 / xcal, 1.0 / ycal, 1.0 / zcal, &wx, &wy, &wz, &wxy, &wxz, &wyz, &wxyz); Length= wx * lx + wy * ly + wz * lz + wxy * (lxy + lx_y) + wxz * (lxz + lx_z) + wyz * (lyz + ly_z) + wxyz * (lxyz + lxy_z + lx_yz + lx_y_z); */ Length= (lx + ly + lz) / 3.0; if (rosel) { rosel[0]= 1.0 / 3.0; rosel[1]= lx / Length; rosel[2]= 1.0 / 3.0; rosel[3]= ly / Length; rosel[4]= 1.0 / 3.0; rosel[5]= lz / Length; rosel[6]= 0.0; rosel[7]= 0.0; rosel[8]= 0.0; rosel[9]= 0.0; rosel[10]= 0.0; rosel[11]= 0.0; rosel[12]= 0.0; rosel[13]= 0.0; rosel[14]= 0.0; rosel[15]= 0.0; rosel[16]= 0.0; rosel[17]= 0.0; rosel[18]= 0.0; rosel[19]= 0.0; rosel[20]= 0.0; rosel[21]= 0.0; rosel[22]= 0.0; rosel[23]= 0.0; rosel[24]= 0.0; rosel[25]= 0.0; } EulerNo= 0.5 * ne; } template void Euler3D0(Binary& I, double& EulerNo6, double& EulerNo18, double& EulerNo26) { //TODO: okr. efekty - anizotropie size_t *p1, *p2, *p3, *p5, *p6, a, b, c, d, e, f, g, h, ae, bf, cg, dh, msk, ms; ptrdiff_t ne6, ne18, ne26; ptrdiff_t numint, numg, i, j, k; ptrdiff_t width= I.dims[0]; ptrdiff_t height= I.dims[1]; ptrdiff_t depth= I.dims[2]; numint= (width + Numb - 1) / Numb; numg= numint * height; msk= ((width % Numb) == 0)?(AB):(AB << (Numb - (width % Numb))); ms= msk << 1; ne6= 0; ne18= 0; ne26= 0; if (numint > 0) { p1= I.data; for (i=1 ; i < numint; i++) { p3= p1 + 1; p6= p3 + numg; p2= p1; p5= p2 + numg; for (k= 1; k < depth; k++){ e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); g= *p5; h= (*p6 & LB)?(RB | (g << 1)):(g << 1); for (j= 1; j < height; j++) { p2+= numint; p5+= numint; p3+= numint; p6+= numint; a= e; b= f; c= g; d= h; e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); g= *p5; h= (*p6 & LB)?(RB | (g << 1)):(g << 1); ae= a & e; bf= b & f; cg= c & g; ne6+= bitnum(e & ~f & ~g) - bitnum(e & f & g & ~h) - bitnum(ae & ~bf & ~cg) + bitnum(ae & bf & cg & ~(d & h)); ae= a | e; bf= b | f; cg= c | g; dh= d | h; ne26+= bitnum(ae & ~bf & ~cg & ~dh) - bitnum(bf & cg & ~dh) - bitnum(e & ~f & ~g & ~h) + bitnum(f & g & ~h); ne18+= bitnum(ae & ~bf & ~cg) - bitnum(ae & bf & cg & ~dh) - bitnum(e & ~f & ~g & ~h) + bitnum(f & g & ~h); } p2+= numint; p5+= numint; p3+= numint; p6+= numint; } e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); for (j= 1; j < height; j++) { p2+= numint; p5+= numint; p3+= numint; p6+= numint; a= e; b= f; e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); } p1++; } p2= p1; p5= p2 + numg; for (k= 1; k < depth; k++){ e= *p2 & msk; f= e << 1; g= *p5 & msk; h= g << 1; for (j= 1; j < height; j++) { p2+= numint; p5+= numint; a= e; b= f; c= g; d= h; e= *p2 & msk; f= e << 1; g= *p5 & msk; h= g << 1; ae= a & e; bf= b & f; cg= c & g; ne6+= bitnum((e & ~f & ~g) & ms) - bitnum((e & f & g & ~h) & ms) - bitnum((ae & ~bf & ~cg) & ms) + bitnum((ae & bf & cg & ~(d & h)) & ms); ae= a | e; bf= b | f; cg= c | g; dh= d | h; ne26+= bitnum((ae & ~bf & ~cg & ~dh) & ms) - bitnum((bf & cg & ~dh) & ms) - bitnum((e & ~f & ~g & ~h) & ms) + bitnum((f & g & ~h) & ms); ne18+= bitnum((ae & ~bf & ~cg) & ms) - bitnum((ae & bf & cg & ~dh) & ms) - bitnum((e & ~f & ~g & ~h) & ms) + bitnum((f & g & ~h) & ms); } p2+= numint; p5+= numint; } e= *p2 & msk; f= e << 1; for (j= 1; j < height; j++) { p2+= numint; p5+= numint; a= e; b= f; e= *p2 & msk; f= e << 1; } } #undef EINCRM EulerNo6= ne6; EulerNo18= ne18; EulerNo26= ne26; } template void Euler3D(Binary& I, double& EulerNo6, double& EulerNo18, double& EulerNo26) { //TODO: okr. efekty - anizotropie size_t *p1, *p2, *p3, *p5, *p6, a, b, c, d, e, f, g, h, ae, bf, cg, dh, msk, ms; ptrdiff_t ne6, ne18, ne26; ptrdiff_t numint, numg, i, j, k; ptrdiff_t width= I.dims[0]; ptrdiff_t height= I.dims[1]; ptrdiff_t depth= I.dims[2]; numint= (width + Numb - 1) / Numb; numg= numint * height; msk= ((width % Numb) == 0)?(AB):(AB << (Numb - (width % Numb))); ms= msk << 1; ne6= 0; ne18= 0; ne26= 0; if (numint > 0) { p1= I.data; for (i=1 ; i < numint; i++) { p3= p1 + 1; p6= p3 + numg; p2= p1; p5= p2 + numg; for (k= 1; k < depth; k++){ e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); g= *p5; h= (*p6 & LB)?(RB | (g << 1)):(g << 1); for (j= 1; j < height; j++) { p2+= numint; p5+= numint; p3+= numint; p6+= numint; a= e; b= f; c= g; d= h; e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); g= *p5; h= (*p6 & LB)?(RB | (g << 1)):(g << 1); ne6+= bitnum(a) - bitnum(a & b) - bitnum(a & c) - bitnum(a & e) + bitnum(a & b & c & d) + bitnum(a & b & e & f) + bitnum(a & e & c & g) - bitnum(a & b & c & d & e & f & g & h); ne26-= bitnum(a) - bitnum(a | b) - bitnum(a | c) - bitnum(a | e) + bitnum(a | b | c | d) + bitnum(a | b | e | f) + bitnum(a | e | c | g) - bitnum(a | b | c | d | e | f | g | h); ae= a | e; bf= b | f; cg= c | g; dh= d | h; ne18+= bitnum(ae & ~bf & ~cg) - bitnum(ae & bf & cg & ~dh) - bitnum(e & ~f & ~g & ~h) + bitnum(f & g & ~h); } p2+= numint; p5+= numint; p3+= numint; p6+= numint; } e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); for (j= 1; j < height; j++) { p2+= numint; p5+= numint; p3+= numint; p6+= numint; a= e; b= f; e= *p2; f= (*p3 & LB)?(RB | (e << 1)):(e << 1); } p1++; } p2= p1; p5= p2 + numg; for (k= 1; k < depth; k++){ e= *p2 & msk; f= e << 1; g= *p5 & msk; h= g << 1; for (j= 1; j < height; j++) { p2+= numint; p5+= numint; a= e; b= f; c= g; d= h; e= *p2 & msk; f= e << 1; g= *p5 & msk; h= g << 1; ne6+= bitnum(a & ms) - bitnum((a & b) & ms) - bitnum((a & c) & ms) - bitnum((a & e) & ms) + bitnum((a & b & c & d) & ms) + bitnum((a & b & e & f) & ms) + bitnum((a & e & c & g) & ms) - bitnum((a & b & c & d & e & f & g & h) & ms); ne26-= bitnum(a & ms) - bitnum((a | b) & ms) - bitnum((a | c) & ms) - bitnum((a | e) & ms) + bitnum((a | b | c | d) & ms) + bitnum((a | b | e | f) & ms) + bitnum((a | e | c | g) & ms) - bitnum((a | b | c | d | e | f | g | h) & ms); ae= a | e; bf= b | f; cg= c | g; dh= d | h; ne18+= bitnum((ae & ~bf & ~cg) & ms) - bitnum((ae & bf & cg & ~dh) & ms) - bitnum((e & ~f & ~g & ~h) & ms) + bitnum((f & g & ~h) & ms); } p2+= numint; p5+= numint; } e= *p2 & msk; f= e << 1; for (j= 1; j < height; j++) { p2+= numint; p5+= numint; a= e; b= f; e= *p2 & msk; f= e << 1; } } #undef EINCRM EulerNo6= ne6; EulerNo18= ne18; EulerNo26= ne26; } //Binary Gray resampling************************************************************************** template void resample_binary_2d(size_t *indat, unsigned char *outdat, ptrdiff_t width, ptrdiff_t height, int num) { ptrdiff_t i, j, k, ints, n2, nheight, nwidth; size_t msk, msk0, msk1, c, d, e, *p1, *p2, *p3; unsigned char *o; double quot; ints= (width + Numb - 1) / Numb; n2= 1 << num; quot= 255.0 / n2 / n2; nwidth= width / n2; nheight= height / n2; for (i= 0, msk0= 0, c= LB; i < n2; i++, c>>= 1) msk0|= c; for (i= 0, msk1= 0, c= 1; i < n2; i++, c<<= 1) msk1|= c; p1= indat; o= outdat; for (i= 0; i < nheight; i++) { for (j= 0, p2= p1, c= LB, msk= msk0, e= Numb - n2; j < nwidth; j++, o++, msk>>= n2, e-= n2) { if (msk == 0) { msk= msk0; e= Numb - n2; p2++; } for (k= 0, p3= p2, d= 0; k < n2; k++, p3+= ints) d+= narr[((*p3) >> e) & msk1]; *o= (unsigned char)((double) d * quot); } p1+= n2 * ints; } } template Image* BinResample2D (Binary& I, const int xy) { if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); int i; int n2= 1 << xy; int *dims; dims= new int[I.nDim]; for (i= 0; i < 2; i++) dims[i]= I.dims[i] / n2; for (i= 2; i < I.nDim; i++) dims[i]= I.dims[i]; Image *O= new Image(I.nDim,dims); O->NewData(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t istep= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1]; ptrdiff_t ostep= dims[0] * dims[1]; size_t* q= I.data; unsigned char* p= O->data; for (i= 0; i < numslic; i++, q+= istep, p+= ostep) resample_binary_2d(q, p, I.dims[0], I.dims[1], xy); delete[] dims; O->SetBounds(I.bounds); return O; } template void resample_binary_3d(size_t *indat, unsigned char *outdat, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, int num, int numz) { ptrdiff_t h, i, j, k, l, ints, n2, n2z, nheight, nwidth, ndepth, ssize; size_t msk, msk0, msk1, c, d, e, *p0, *p1, *p2, *p3, *p4; unsigned char *o; double quot; ints= (width + Numb - 1) / Numb; n2= 1 << num; n2z= 1 << numz; quot= 255.0 / n2 / n2 / n2z; ssize= height * ints; nwidth= width / n2; nheight= height / n2; ndepth= depth / n2z; for (i= 0, msk0= 0, c= LB; i < n2; i++, c>>= 1) msk0|= c; for (i= 0, msk1= 0, c= 1; i < n2; i++, c<<= 1) msk1|= c; p0= indat; o= outdat; for (h= 0; h < ndepth; h++) { for (i= 0, p1= p0; i < nheight; i++) { for (j= 0, p2= p1, c= LB, msk= msk0, e= Numb - n2; j < nwidth; j++, o++, msk>>= n2, e-= n2) { if (msk == 0) { msk= msk0; e= Numb - n2; p2++; } for (k= 0, p3= p2, d= 0; k < n2; k++, p3+= ints) for (l= 0, p4= p3; l < n2z; l++, p4+= ssize) d+= narr[((*p4) >> e) & msk1]; *o= (unsigned char)((double) d * quot); } p1+= n2 * ints; } p0+= n2z * ssize; } } template Image* BinResample3D (Binary& I, const int xy, const int z) { if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); ptrdiff_t i; int n2= 1 << xy; int n2z= 1 << z; ptrdiff_t *dims; dims= new ptrdiff_t[I.nDim]; for (i= 0; i < 2; i++) dims[i]= I.dims[i] / n2; dims[2]= I.dims[2] / n2z; for (i= 3; i < I.nDim; i++) dims[i]= I.dims[i]; Image *O= new Image(I.nDim,dims); O->NewData(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t istep= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; ptrdiff_t ostep= dims[0] * dims[1] * dims[2]; size_t* q= I.data; unsigned char* p= O->data; for (i= 0; i < numslic; i++, q+= istep, p+= ostep) resample_binary_3d(q, p, I.dims[0], I.dims[1], I.dims[2], xy, z); delete[] dims; O->SetBounds(I.bounds); return O; } //Structures************************************************************************************** class Stack2UInt { std::vector st; public: ptrdiff_t Pop(ptrdiff_t& i1, ptrdiff_t& i2) { if (!st.empty()) { i2= st.back(); st.pop_back(); i1= st.back(); st.pop_back(); return true; } else return false; } void Push(const ptrdiff_t& i1, const ptrdiff_t& i2) { st.push_back(i1); st.push_back(i2); } }; class Queue3UInt { std::queue q; public: ptrdiff_t Pop(ptrdiff_t& i1, ptrdiff_t& i2, ptrdiff_t& i3) { if (!q.empty()) { i1= q.front(); q.pop(); i2= q.front(); q.pop(); i3= q.front(); q.pop(); return true; } else return false; } void Push(const ptrdiff_t& i1, const ptrdiff_t& i2, const ptrdiff_t& i3) { q.push(i1); q.push(i2); q.push(i3); } }; //Utilities*************************************************************************************** template void Threshold (Image& I, Binary& B, const F value, thrmod thr = thrgt) { if (!I.data || !B.data) throw Allocerr(); if (B.nDim != I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,B.dims)) throw Sizeerr(); ptrdiff_t nlin= DimsProd (I.nDim - 1, I.dims + 1); ptrdiff_t ncol= I.dims[0]; F* pin= I.data; size_t* pout= B.data; size_t k= LB, c= 0; ptrdiff_t i, j; #define CASE(OP) \ for (i= 0; i < nlin; i++) { \ for (j= 0; j < ncol; j++, pin++) { \ if (*pin OP value) c|= k; \ k= k >> 1; \ if (k == 0) { \ k= LB; \ *pout= c; \ pout++; \ c= 0; \ } \ } \ if (k != LB) { \ k= LB; \ *pout= c; \ pout++; \ c= 0; \ } \ } \ break; switch (thr) { case thrgt: CASE(>) case thrge: CASE(>=) case thrlt: CASE(<) case thrle: CASE(<=) case thre: CASE(==) } B.EraseEnd(); return; } template void Threshold (Image& I, Binary& B, const F value1, const F value2) { if (!I.data || !B.data) throw Allocerr(); if (B.nDim != I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,B.dims)) throw Sizeerr(); ptrdiff_t nlin= DimsProd (I.nDim - 1, I.dims + 1); ptrdiff_t ncol= I.dims[0]; F* pin= I.data; size_t* pout= B.data; size_t k= LB, c= 0; ptrdiff_t i, j; for (i= 0; i < nlin; i++) { for (j= 0; j < ncol; j++, pin++) { if ((value1 < *pin)&&(value2 >= *pin)) c|= k; k= k >> 1; if (k == 0) { k= LB; *pout= c; pout++; c= 0; } } if (k != LB) { k= LB; *pout= c; pout++; c= 0; } } B.EraseEnd(); return; } template void Combine (Image& I, Binary& B, Image& J, binmod mode= binpos) { if (!I.data || !B.data || !J.data) throw Allocerr(); if ((B.nDim != I.nDim) || (B.nDim != J.nDim)) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,B.dims) || !DimsEq(J.nDim,J.dims,B.dims)) throw Sizeerr(); ptrdiff_t nlin= DimsProd (I.nDim - 1, I.dims + 1); ptrdiff_t ncol= I.dims[0]; F* pio= I.data; G* pin= J.data; size_t* pib= B.data; size_t k= LB; ptrdiff_t i,j; //TODO:speed up pib for (i= 0; i < nlin; i++) { if (mode == binpos) for (j= 0; j < ncol; j++, pio++, pin++) { if (*pib & k) *pio= *pin; k= k >> 1; if (k == 0) { k= LB; pib++; } } else for (j= 0; j < ncol; j++, pio++, pin++) { if (!(*pib & k)) *pio= *pin; k= k >> 1; if (k == 0) { k= LB; pib++; } } if (k != LB) { k= LB; pib++; } } return; } template void Combine (Image& I, Binary& B, const G val, binmod mode= binpos) { if (!I.data || !B.data) throw Allocerr(); if (B.nDim != I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,B.dims)) throw Sizeerr(); ptrdiff_t nlin= DimsProd (I.nDim - 1, I.dims + 1); ptrdiff_t ncol= I.dims[0]; F* pio= I.data; size_t* pib= B.data; size_t k= LB; ptrdiff_t i,j; //TODO:speed up pib for (i= 0; i < nlin; i++) { if (mode == binpos) for (j= 0; j < ncol; j++, pio++) { if (*pib & k) *pio= val; k= k >> 1; if (k == 0) { k= LB; pib++; } } else for (j= 0; j < ncol; j++, pio++) { if (!(*pib & k)) *pio= val; k= k >> 1; if (k == 0) { k= LB; pib++; } } if (k != LB) { k= LB; pib++; } } return; } template void MeasureG (Binary& B, Image& I, ptrdiff_t &Num, double &Mean) { if (!I.data || !B.data) throw Allocerr(); if (B.nDim != I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,B.dims)) throw Sizeerr(); ptrdiff_t nlin= DimsProd (I.nDim - 1, I.dims + 1); ptrdiff_t ncol= I.dims[0]; double sum= 0.0; ptrdiff_t n= 0; F* pin= I.data; size_t* pib= B.data; size_t k= LB; ptrdiff_t i,j; //TODO:speed up pib for (i= 0; i < nlin; i++) { for (j= 0; j < ncol; j++, pin++) { if (*pib & k) { sum+= *pin; n++; } k= k >> 1; if (k == 0) { k= LB; pib++; } } if (k != LB) { k= LB; pib++; } } Num= n; Mean= sum / (double)n; return; } //Gray drawing************************************************************************************ template void putpixel_gray(F *image, int nDim, ptrdiff_t *dims, double *x, double *cooar, int nvar) { ptrdiff_t *s, poloha, index, ok, pom, i, j; double *p, *q, *value; F *pimg; ok= true; q= cooar; p= x; for (i= 0; i < nDim; i++, p++, q+= 2) ok&= (*p >= *q) && (*p < *(q + 1)); if (ok) { p--; q-= 2; s= dims + (nDim - 1); poloha= 0; for (i= 0; i < nDim; i++, s--, p--, q-= 2) { pom= (ptrdiff_t)((*p - *q) / ((*(q + 1) - *q) / *s)/* + 0.5*/); index= (pom >= *s)?(*s - 1):((pom < 0)?0:pom); poloha= *s * poloha + index; } value= x + nDim; pimg= image + poloha * nvar; for (j= 0; j < nvar; j++, pimg++, value++) *pimg= *value; } } template ptrdiff_t getpixel_gray(F *image, int nDim, ptrdiff_t *dims, double *x, double *cooar, int nvar) { ptrdiff_t *s, poloha, index, ok, i, j; double *p, *q, *value; F *pimg; ok= true; q= cooar; p= x; for (i= 0; i < nDim; i++, p++, q+= 2) ok&= (*p >= *q) && (*p < *(q + 1)); if (ok) { p--; q-= 2; s= dims + (nDim - 1); poloha= 0; for (i= 0; i < nDim; i++, s--, p--, q-= 2) { index= (ptrdiff_t)((*p - *q) / ((*(q + 1) - *q) / *s)/* + 0.5*/); if ((index >= *s)||(index < 0)) return 0; poloha= *s * poloha + index; } value= x + nDim; pimg= image + poloha * nvar; for (j= 0; j < nvar; j++, pimg++, value++) *value= *pimg; return 1; } else return 0; } template void line_gray(F *image, int nDim, ptrdiff_t *dims, double *x1i, double *x2i, double *cooar, int nvar) { ptrdiff_t *s, poloha, index, ok, pom, i, j, maxn, isteps; double *p1, *p2, *p, *q, *x, *dx, max, steps, pf, *x1, *x2, *r, *dc, *value, *pvalue; F *pimg; if (((dc= (double *)malloc(nDim * sizeof(double))) == NULL) ||((x1= (double *)malloc(nDim * sizeof(double))) == NULL) ||((x2= (double *)malloc(nDim * sizeof(double))) == NULL)) { throw Memerr(); } memcpy(x1, x1i, nDim * sizeof(double)); memcpy(x2, x2i, nDim * sizeof(double)); for (i= 0; i < nDim; i++) { dc[i]= (cooar[2 * i + 1] - cooar[2 * i]) / dims[i]; } if (!clipline(nDim, x1, x2, cooar)) return; for (i= 0,q= cooar,p1= x1,p2= x2,s= dims,ok= false,r=dc; i < nDim; i++,s++,p1++,p2++,q+= 2,r++) ok|= (ptrdiff_t)((*p1 - *q) / *r) != (ptrdiff_t)((*p2 - *q)/ *r); if (!ok) { putpixel_gray(image, nDim, dims, x1, cooar, nvar); free(x1); free(x2); free(dc); return; } if (((dx= (double *)malloc(nDim * sizeof(double))) == NULL) ||((x= (double *)malloc(nDim * sizeof(double))) == NULL)) { throw Memerr(); } for (i= 0; i < nDim; i++) { x[i]= x1[i] /* + 0.5*/; dx[i]= x2[i] - x1[i]; } value= x1i + nDim; for (i= 0,max= 0.0,maxn= 0; i < nDim; i++) if ((pf= (fabs(dx[i]) / dc[i])) > max) { max= pf; maxn= i; } steps=fabs(dx[maxn])/dc[maxn];; for (i= 0; i < nDim; i++) dx[i]/= steps; isteps= (ptrdiff_t)steps; for (j= 0; j <= isteps; j++) { q= cooar + 2 * (nDim - 1); p= x + (nDim - 1); s= dims + (nDim - 1); r= dc + (nDim - 1); poloha= 0; for (i= 0; i < nDim; i++, s--, p--, q-= 2, r--) { pom= (ptrdiff_t)((*p - *q) / *r); index= (pom >= *s)?(*s - 1):((pom < 0)?0:pom); poloha= *s * poloha + index; } pvalue= value; pimg= image + poloha * nvar; for (i= 0; i < nvar; i++, pimg++, pvalue++) *pimg= *pvalue; for (i= 0, p= x, q= dx; i < nDim; i++) *(p++)+= *(q++); } free(x); free(x1); free(x2); free(dx); free(dc); } template void Points(Image& I, Object& O) { if (!I.data) throw Allocerr(); if (O.nVar < (I.nDim + I.nVars)) throw NVarerr(); putpixel_gray(I.data, I.nDim, I.dims, O.data, I.bounds, I.nVars); } template void Points(Image& I, ObjectArray& O) { if (!I.data) throw Allocerr(); for (ObjectArray::iterator io = O.begin (); io != O.end (); io++) { if (io->nVar < (I.nDim + I.nVars)) throw NVarerr(); putpixel_gray(I.data, I.nDim, I.dims, io->data, I.bounds, I.nVars); } } template void Polyline(Image& I, ObjectArray& O) { if (!I.data) throw Allocerr(); for (ObjectArray::iterator io = O.begin (); (io + 1) != O.end(); io++) { if ((io->nVar < (I.nDim + I.nVars))||((io + 1)->nVar < I.nDim)) throw NVarerr(); line_gray(I.data, I.nDim, I.dims, io->data, (io + 1)->data, I.bounds, I.nVars); } } template void Segments(Image& I, ObjectArray& O) { if (!I.data) throw Allocerr(); for (ObjectArray::iterator io = O.begin (); (io != O.end())&&((io + 1) != O.end()); io+= 2) { if ((io->nVar < (I.nDim + I.nVars))||((io + 1)->nVar < I.nDim)) throw NVarerr(); line_gray(I.data, I.nDim, I.dims, io->data, (io + 1)->data, I.bounds, I.nVars); } } //Utilities********************************************************************************* //slice template Frame* SliceFrame (Frame& I, const int dimension) { if (dimension >= I.nDim) throw Argerr(); ptrdiff_t* outdims= new ptrdiff_t[I.nDim - 1]; ptrdiff_t i, j= 0; for (i= 0; i < I.nDim; i++) if (i != dimension) { outdims[j]= I.dims[i]; j++; } Frame* O = new Frame(I.nDim - 1, outdims); delete[] outdims; return O; } template void SliceData (Image& I, Image& O, const int dimension, const ptrdiff_t index) { if (!I.data) throw Allocerr(); if ((dimension >= I.nDim) || (index >= I.dims[dimension])) throw Argerr(); if (O.nDim != (I.nDim - 1)) throw Dimserr(); if (!DimsEqProj(I.nDim,O.dims,I.dims,dimension)) throw Sizeerr(); if (I.nVars!=O.nVars) throw NVarerr(); if (!O.data) O.NewData(); ptrdiff_t nData= DimsProdEx(I.nDim, I.dims, dimension) * I.nVars; int dataLen= sizeof(F); ptrdiff_t nInter = DimsProd(dimension, I.dims, I.nVars); ptrdiff_t nStep = DimsProd(dimension + 1, I.dims, I.nVars); ptrdiff_t nBegin = index * nInter; F* indata= I.data; F* odata= O.data; indata += nBegin; ptrdiff_t i; for(i= 0; i < nData; i+= nInter) { memcpy(odata, indata, dataLen * nInter); indata += nStep; odata += nInter; } return; } template Image* Slice (Image& I, const int dimension, const ptrdiff_t index) { Frame *Frm= SliceFrame(I,dimension); Image *O= new Image(*Frm,I.nVars); delete Frm; O->NewData(); SliceData(I,*O,dimension,index); return O; } //projection template void ProjectionData (Image& I, Image& O, const int dimension) { if (!I.data) throw Allocerr(); if (dimension >= I.nDim) throw Argerr(); if (O.nDim != (I.nDim - 1)) throw Dimserr(); if (I.nVars!=O.nVars) throw NVarerr(); if (!DimsEqProj(I.nDim,O.dims,I.dims,dimension)) throw Sizeerr(); if (!O.data) O.NewData(); ptrdiff_t nData= DimsProdEx(I.nDim, I.dims, dimension) * I.nVars; ptrdiff_t nInter = DimsProd(dimension, I.dims, I.nVars); ptrdiff_t nLine= I.dims[dimension]; ptrdiff_t nStep = nInter * (nLine - 1); F* indata= I.data; F* odata= O.data; F *p, q; ptrdiff_t i,j,k; for(i= 0; i < nData; i+= nInter) { for(j= 1; j < nInter; j++) { p= indata++; q= *p; p+= nInter; for(k= 1; k < nLine ; k++, p+= nInter) if(*p > q) q= *p; *(odata++)= q; } indata += nStep; } return; } template Image* Projection (Image& I, const int dimension) { Frame *Frm= SliceFrame(I,dimension); Image *O= new Image(*Frm,I.nVars); delete Frm; O->NewData(); ProjectionData(I,*O,dimension); return O; } //crop template Frame* CropFrame (const Frame& I, const BoundBox& J) { Frame* O= new Frame(I.nDim); int i; for (i= 0; i < I.nDim; i++) { double cal= I.Dx(i); ptrdiff_t x1= (ptrdiff_t)(floor((J.bounds[2 * i] - I.bounds[2 * i]) / cal + 0.5)); O->dims[i]= (ptrdiff_t)(floor((J.bounds[2 * i + 1] - J.bounds[2 * i]) / cal + 0.5)); if (O->dims[i] < 1) O->dims[i]= 1; O->bounds[2 * i]= I.bounds[2 * i] + x1 * cal; O->bounds[2 * i + 1]= O->bounds[2 * i] + O->dims[i] * cal; } return O; } template void CropData (Image& I, const Frame& J, Image& O) { if (O.nDim != J.nDim) throw Dimserr(); if (!DimsEq(J.nDim, J.dims, O.dims)) throw Sizeerr(); if (I.nVars!=O.nVars) throw NVarerr(); int nDim= I.nDim; ptrdiff_t *d1i= new ptrdiff_t[nDim]; ptrdiff_t *d2i= new ptrdiff_t[nDim]; ptrdiff_t *d1o= new ptrdiff_t[nDim]; ptrdiff_t *d2o= new ptrdiff_t[nDim]; ptrdiff_t *num= new ptrdiff_t[nDim]; ptrdiff_t *cnt= new ptrdiff_t[nDim]; ptrdiff_t i; int ni= I.nVars; int no= O.nVars; for (i= 0; i < nDim; i++) { double cal= I.Dx(i); ptrdiff_t x1= (ptrdiff_t)(floor((J.bounds[2 * i] - I.bounds[2 * i]) / cal + 0.5)); ptrdiff_t x2= x1 + J.dims[i] - 1; ptrdiff_t x01= 0; ptrdiff_t x02= I.dims[i] - 1; if ((x1 > x02)||(x2 < x01)) { delete[] d1i; delete[] d2i; delete[] d1o; delete[] d2o; delete[] cnt; delete[] num; return; } ptrdiff_t xx1, xx2; if (x1 < x01) xx1= x01; else xx1= x1; if (x2 >= x02) xx2= x02; else xx2= x2; num[i]= xx2 - xx1 + 1; d1i[i]= (xx1 - x01) * ni; d2i[i]= (x02 - xx2) * ni; d1o[i]= (xx1 - x1) * no; d2o[i]= (x2 - xx2) * no; ni= ni * I.dims[i]; no= no * J.dims[i]; cnt[i]= 0; } ptrdiff_t tocopy= DimsProd(nDim, num, I.nVars); ptrdiff_t linelen= num[0] * I.nVars; F *p= I.data; G *q= O.data; for (i= nDim - 1; i > 0; i--) { p+= d1i[i]; q+= d1o[i]; } while (tocopy > 0) { p+= d1i[0]; q+= d1o[0]; for (i= 0; i < linelen; i++, p++, q++) *q= *p; tocopy-= linelen; p+= d2i[0]; q+= d2o[0]; i= 1; cnt[1]++; if (tocopy > 0) { while ((i < (nDim - 1))&&(cnt[i] >= num[i])) { cnt[i]= 0; p+= d2i[i]; q+= d2o[i]; i++; cnt[i]++; } while (i > 1) { i--; p+= d1i[i]; q+= d1o[i]; } } } delete[] d1i; delete[] d2i; delete[] d1o; delete[] d2o; delete[] cnt; delete[] num; } template Image* Crop (Image& I, const BoundBox& J, double val= 0) { if (I.nDim != J.nDim) throw Dimserr(); Frame *Frm= CropFrame(I,J); Image *O= new Image(*Frm,I.nVars); O->NewData(); O->SetData(IL_GU_SET,val); CropData(I,*Frm,*O); delete Frm; return O; } //paint template void PaintData (Image& I, Image& J) { if (I.nDim != J.nDim) throw Dimserr(); if (I.nVars != J.nVars) throw NVarerr(); int nDim= I.nDim; ptrdiff_t *d1i= new ptrdiff_t[nDim]; ptrdiff_t *d2i= new ptrdiff_t[nDim]; ptrdiff_t *d1o= new ptrdiff_t[nDim]; ptrdiff_t *d2o= new ptrdiff_t[nDim]; ptrdiff_t *num= new ptrdiff_t[nDim]; ptrdiff_t *cnt= new ptrdiff_t[nDim]; int i; int ni= I.nVars; int no= J.nVars; for (i= 0; i < nDim; i++) { double cal= I.Dx(i); ptrdiff_t x1= (ptrdiff_t)(floor((J.bounds[2 * i] - I.bounds[2 * i]) / cal + 0.5)); ptrdiff_t x2= x1 + J.dims[i] - 1; ptrdiff_t x01= 0; ptrdiff_t x02= I.dims[i] - 1; if ((x1 > x02)||(x2 < x01)) { delete[] d1i; delete[] d2i; delete[] d1o; delete[] d2o; delete[] cnt; delete[] num; return; } ptrdiff_t xx1, xx2; if (x1 < x01) xx1= x01; else xx1= x1; if (x2 >= x02) xx2= x02; else xx2= x2; num[i]= xx2 - xx1 + 1; d1i[i]= (xx1 - x01) * ni; d2i[i]= (x02 - xx2) * ni; d1o[i]= (xx1 - x1) * no; d2o[i]= (x2 - xx2) * no; ni= ni * I.dims[i]; no= no * J.dims[i]; cnt[i]= 0; } ptrdiff_t tocopy= DimsProd(nDim, num, I.nVars); ptrdiff_t linelen= num[0] * I.nVars; F *p= I.data; G *q= J.data; for (i= nDim - 1; i > 0; i--) { p+= d1i[i]; q+= d1o[i]; } while (tocopy > 0) { p+= d1i[0]; q+= d1o[0]; for (i= 0; i < linelen; i++, p++, q++) *p= *q; //oposite to crop tocopy-= linelen; p+= d2i[0]; q+= d2o[0]; i= 1; cnt[1]++; if (tocopy > 0) { while ((i < (nDim - 1))&&(cnt[i] >= num[i])) { cnt[i]= 0; p+= d2i[i]; q+= d2o[i]; i++; cnt[i]++; } while (i > 1) { i--; p+= d1i[i]; q+= d1o[i]; } } } delete[] d1i; delete[] d2i; delete[] d1o; delete[] d2o; delete[] cnt; delete[] num; } //resample template Frame* Resample1DFrame (const Frame& I, const int dimension, const double factor) { if (dimension >= I.nDim) throw Argerr(); ptrdiff_t* outdims= new ptrdiff_t[I.nDim]; int i; for (i= 0; i < I.nDim; i++) if (i != dimension) outdims[i]= I.dims[i]; else { outdims[i]= (ptrdiff_t)(factor * I.dims[i]); if (outdims[i] < 1) outdims[i]= 1; } Frame* O = new Frame(I.nDim, outdims, I.bounds); delete[] outdims; return O; } template Frame* Resample1DFrame (const Frame& I, const int dimension, const Frame& B) { if ((dimension >= I.nDim)||(dimension >= B.nDim)) throw Argerr(); ptrdiff_t* outdims= new ptrdiff_t[I.nDim]; int i; for (i= 0; i < I.nDim; i++) if (i != dimension) outdims[i]= I.dims[i]; else outdims[i]= B.dims[i]; Frame* O = new Frame(I.nDim, outdims, I.bounds); delete[] outdims; return O; } template void Resample1DData (Image& I, Image& O, const int dimension, const resmet method =reslin) { if (!I.data) throw Allocerr(); if (dimension >= I.nDim) throw Argerr(); if (O.nDim != I.nDim) throw Dimserr(); if (I.nVars!=O.nVars) throw NVarerr(); if (!DimsEqEx(O.nDim,O.dims,I.dims,dimension)) throw Sizeerr(); if (!O.data) O.NewData(); ptrdiff_t nData= DimsProd(I.nDim, I.dims, I.nVars) / I.dims[dimension]; ptrdiff_t dataLen= sizeof(F); ptrdiff_t nInter = DimsProd(dimension, I.dims, I.nVars); ptrdiff_t iLine= I.dims[dimension]; ptrdiff_t iStep= nInter * (iLine - 1); ptrdiff_t oLine= O.dims[dimension]; ptrdiff_t oStep= nInter * (oLine - 1); F* indata= I.data; F* outdata= O.data; double fact= (double)oLine / (double)iLine; ptrdiff_t i, j, k, l; double a, b, d, e; F *p, *q; if (oLine == iLine) { ptrdiff_t nD= DimsProd(I.nDim, I.dims, I.nVars); for (i= 0; i < nD; i++) *(outdata++)= *(indata++); } else switch (method) { case resnear: //TODO modus if (fact < 1.0) { double d2= 1.0 / fact; for(i= 0; i < nData; i+= nInter) { for(j= 0; j < nInter; j++) { b= 0.5 * d2; d= 0.0; p= indata++; q= outdata++; for (l= 0, k= 1; (l < oLine)&&(k <= iLine); l++, q+= nInter, b+= d2) { while ((k < b)&&(k <= iLine)) { p+= nInter; k++; } if (k <= iLine) { *q= *p; p+= nInter; k++; } else *q= *p; } } indata+= iStep; outdata+= oStep; } } else { double d2= (double)(iLine - 1) / (double)(oLine - 1); for(i= 0; i < nData; i+= nInter) { for(j= 0; j < nInter; j++) { p= indata++; q= outdata++; for (k= 0, l= 0, a= 0.5; k < oLine; k++) { *q= *p; q+= nInter; a+= d2; if ((a >= 1.0)&&(l < (iLine - 2))) { a-= 1.0; p+= nInter; l++; } } } indata+= iStep; outdata+= oStep; } } break; case reslin: if (fact < 1.0) { double d2= 1.0 / fact; for(i= 0; i < nData; i+= nInter) { for(j= 0; j < nInter; j++) { b= d2; d= 0.0; p= indata++; q= outdata++; for (l= 0, k= 1; (l < oLine)&&(k <= iLine); l++, q+= nInter, b+= d2) { while ((k < b)&&(k <= iLine)) { d+= (double)*p; p+= nInter; k++; } if (k <= iLine) { e= b - k + 1.0; *q= (d + e * (double)*p) / d2; d= (1.0 - e) * (double)*p; p+= nInter; k++; } else *q= d / d2; } } indata+= iStep; outdata+= oStep; } } else { double d2= (double)(iLine - 1) / (double)(oLine - 1); for(i= 0; i < nData; i+= nInter) { for(j= 0; j < nInter; j++) { p= indata++; q= outdata++; for (k= 0, l= 0, a= 0.0; k < oLine; k++) { *q= a * *(p + nInter) + (1.0 - a) * *p; q+= nInter; a+= d2; if ((a >= 1.0)&&(l < (iLine - 2))) { a-= 1.0; p+= nInter; l++; } } } indata+= iStep; outdata+= oStep; } } break; } O.SetBounds(I.bounds); return; } template Image* Resample1D (Image& I, const int dimension, const double factor, const resmet method= reslin) { Frame *Frm= Resample1DFrame(I,dimension,factor); Image *O= new Image(*Frm,I.nVars); delete Frm; O->NewData(); Resample1DData(I,*O,dimension,method); return O; } template Image* Resample1D (Image& I, const int dimension, const Frame& B, const resmet method= reslin) { Frame *Frm= Resample1DFrame(I,dimension,B); Image *O= new Image(*Frm,I.nVars); delete Frm; O->NewData(); Resample1DData(I,*O,dimension,method); return O; } template Frame* ResampleFrame (const Frame& I, const int dimension, const double factor) { if (dimension > I.nDim) throw Argerr(); ptrdiff_t* outdims= new ptrdiff_t[I.nDim]; int i; for (i= 0; i < dimension; i++) { outdims[i]= (ptrdiff_t)(factor * I.dims[i]); if (outdims[i] < 1) outdims[i]= 1; } for (i= dimension; i < I.nDim; i++) outdims[i]= I.dims[i]; Frame* O = new Frame(I.nDim, outdims, I.bounds); delete[] outdims; return O; } template Frame* ResampleFrame (const Frame& I, const int dimension, const Frame& B) { if ((dimension > I.nDim)||(dimension > B.nDim)) throw Argerr(); ptrdiff_t* outdims= new ptrdiff_t[I.nDim]; int i; for (i= 0; i < dimension; i++) outdims[i]= B.dims[i]; for (i= dimension; i < I.nDim; i++) outdims[i]= I.dims[i]; Frame* O = new Frame(I.nDim, outdims, I.bounds); delete[] outdims; return O; } template void ResampleData (Image& I, Image& O, const int dimension, const resmet method =reslin) { if (O.nDim != I.nDim) throw Dimserr(); if (I.nVars!=O.nVars) throw NVarerr(); if ((dimension < 1)||(dimension > I.nDim)) throw Argerr(); if (!DimsEq(O.nDim - dimension,O.dims + dimension, I.dims + dimension)) throw Sizeerr(); if (!O.data) O.NewData(); if (dimension == 1) { Resample1DData(I,O,0,method); return; } Image *P, *Q; int i; P= Resample1D(I,0,O,method); for (i= 1; i < (dimension - 1); i++) { Q= Resample1D(*P,i,O,method); P->DeleteData(); delete P; P= Q; } Resample1DData(*P,O,dimension - 1,method); P->DeleteData(); delete P; } template Image* Resample (Image& I, const int dimension, const double factor, const resmet method= reslin) { Image *O, *P; int i; if (dimension < 0) throw Argerr(); P= O= Resample1D(I,0,factor,method); for (i= 1; i < dimension; i++) { O= Resample1D(*P,i,factor,method); P->DeleteData(); delete P; P= O; } return O; } template Image* Resample (Image& I, const int dimension, const Frame& B, const resmet method= reslin) { Image *O, *P; int i; if (dimension < 0) throw Argerr(); P= O= Resample1D(I,0,B,method); for (i= 1; i < dimension; i++) { O= Resample1D(*P,i,B,method); P->DeleteData(); delete P; P= O; } return O; } //gaussian template void Gauss1D (Image& I, int dimension, double sigma) { if (!I.data) throw Allocerr(); if (dimension >= I.nDim) throw Argerr(); ptrdiff_t nData= DimsProd(I.nDim, I.dims, I.nVars) / I.dims[dimension]; ptrdiff_t nInter = DimsProd(dimension, I.dims, I.nVars); ptrdiff_t nLine= I.dims[dimension]; ptrdiff_t nStep= nInter * (nLine - 1); ptrdiff_t nVars= I.nVars; F *i0, *i1, *o; ptrdiff_t i, j, k, m, m2, l, fi, n; double *g, *f, sp, *f0, *f1, *g1; double denom; double dx= I.Dx(dimension); const double thresh_k= 0.05; m= ceil(-log(thresh_k) * 2.0 * sigma / dx); if (m < 1) return; m2= 2 * m - 1; g= new double[m2]; f= new double[nLine + 2 * (m - 1)]; if ((!g)||(!f)) throw Memerr(); for (i= 0; i < m2; i++) g[i]= normal((i - m + 1) * dx, sigma); denom= 0.0; for (i= 0; i < m2; i++) denom+= g[i]; for (i= 0; i < m2; i++) g[i]/= denom; for (n= 0; n < nVars; n++) { i1= I.data; i1+= n; for (i= 0; i < nData; i+= nInter) { for (k= 0; k < nInter; k+= nVars) { i0= i1; o= i1; f1= f; for (l= 1; l < m; l++) *(f1++)= *i0; for (l= 1; l < nLine; l++, i0+= nInter) *(f1++)= *i0; for (l= 0; l < m; l++) *(f1++)= *i0; for (j= 0, f0= f; j < nLine; j++, f0++) { sp= 0.0; for (fi= 0, f1= f0, g1= g; fi < m2; fi++) sp+= *(g1++) * *(f1++); *o= sp; o+= nInter; } i1+= nVars; } i1+= nStep; } } delete[] f; delete[] g; } //Young, van Vliet template void Gauss1D_YV (Image& I, int dimension, double sigma) { if (!I.data) throw Allocerr(); if (dimension >= I.nDim) throw Argerr(); ptrdiff_t nData= DimsProd(I.nDim, I.dims, I.nVars) / I.dims[dimension]; ptrdiff_t nInter = DimsProd(dimension, I.dims, I.nVars); ptrdiff_t nLine= I.dims[dimension]; ptrdiff_t nStep= nInter * (nLine - 1); ptrdiff_t nVars= I.nVars; F *i0, *i1, *o; ptrdiff_t i, j, k, n; double *f, *f0; ptrdiff_t np= nLine + 4; double dx= I.Dx(dimension); f= new double[np]; if (!f) throw Memerr(); const double m0= 1.16680; const double m1= 1.10783; const double m2= 1.40586; const double c1= 1.31564; const double c2= 0.490811; double b1, b2, b3, scale, B, Bs, sg, q; sg= sigma / dx; if (sg < 1.0) throw Valerr(); q= c1 * (sqrt(1 + c2 * sg * sg) - 1.0); //sg > 1!!! scale= (m0 + q) * (m1 * m1 + m2 * m2 + 2.0 * m1 * q + q * q); b1= -q * (2.0 * m0 * m1 + m1 * m1 + m2 * m2 + (2.0 * m0 + 4.0 * m1) * q + 3.0 * q * q) / scale; b2= q * q * (m0 + 2.0 * m1 + 3.0 * q) / scale; b3= - q * q * q / scale; Bs= m0 * (m1 * m1 + m2 * m2) / scale; B= Bs * Bs; //Triggs double uplus, unp, unp1, unp2, m11, m12, m13, m21, m22, m23, m31, m32, m33; scale= 1.0 / ((1.0 - b1 + b2 - b3) * (1.0 + b1 + b2 + b3) * (1.0 - b2 + (b1 - b3) * b3)); m11= scale * ( 1.0 - b3 * b1 - b3 * b3 + b2); m12= scale * (b3 + b1) * (b2 - b3 * b1); m13= scale * b3 * (b1 - b3 * b2); m21= scale * (b3 * b2 - b1); m22= scale * (1.0 + b2) * (b3 * b1 - b2); m23= scale * b3 * (b3 * b1 + b3 * b3 - b2 - 1.0); m31= scale * (b3 * b1 - b2 + b1 * b1 - b2 * b2); m32= scale * (b1 * b2 - b3 * b2 * b2 + b1 * b3 * b3 + b3 * b3 * b3 - b3 * b2 - b3); m33= scale * b3 * (b1 - b3 * b2); for (n= 0; n < nVars; n++) { i1= I.data; i1+= n; for (i= 0; i < nData; i+= nInter) { for (k= 0; k < nInter; k+= nVars) { i0= i1; o= i1; f0= f; *(f0++)= *i0; *(f0++)= *i0; for (j= 1; j < nLine; j++, i0+= nInter) *(f0++)= *i0; *(f0++)= *i0; *(f0++)= *i0; *(f0++)= *i0; i0+= nInter; f[0]= f[1]= f[2]= f[0] / (1.0 + b1 + b2 + b3); uplus= f[np-1] / (1.0 + b1 + b2 + b3); for (j= 3; j < np; j++) f[j]-= b1 * f[j-1] + b2 * f[j-2] + b3 * f[j-3]; //T unp= f[np-1] - uplus; unp1= f[np-2] - uplus; unp2= f[np-3] - uplus; uplus/= (1.0 + b1 + b2 + b3); f[np-3]= B * (m11 * unp + m12 * unp1 + m13 * unp2 + uplus); f[np-2]= B * (m21 * unp + m22 * unp1 + m23 * unp2 + uplus); f[np-1]= B * (m31 * unp + m32 * unp1 + m33 * unp2 + uplus); for (j= np - 4; j >= 0; j--) f[j]= B * f[j] - (b1 * f[j+1] + b2 * f[j+2] + b3 * f[j+3]); f0= f + 2; for (j= 0; j < nLine; j++, o+= nInter) *o= *(f0++); i1+= nVars; } i1+= nStep; } } delete[] f; } template void Gauss (Image& I, int ndim, double sigma) { if (!I.data) throw Allocerr(); if (ndim > I.nDim) throw Argerr(); int i; for (i= 0; i < ndim; i++) if (I.Dx(i) > sigma) Gauss1D(I, i, sigma); else Gauss1D_YV(I, i, sigma); } template void shift1d_0(F *in, int nDim, ptrdiff_t *dims, int nVars, int dimension, ptrdiff_t by, double val) { if (!by) return; ptrdiff_t nData= DimsProd(nDim, dims, nVars) / dims[dimension]; ptrdiff_t nInter = DimsProd(dimension, dims, nVars); ptrdiff_t nLine= dims[dimension]; ptrdiff_t nStep= nInter * (nLine - 1); F *indata= in; F *i0, *i1, *i2; ptrdiff_t i, j, k; for(i= 0; i < nData; i+= nInter) { for(j= 0; j < nInter; j++) { i0= indata++; if (by > 0) { if (by > nLine) by= nLine; for (k= by, i1= i0 + (nLine - by - 1) * nInter, i2= i0 + (nLine - 1) * nInter; k < nLine; k++, i1-= nInter, i2-= nInter) *i2= *i1; for (k= 0, i2= i0; k < by; k++, i2+= nInter) *i2= val; } else { if (by < - nLine) by= - nLine; for (k= - by, i2= i0, i1= i0 - by * nInter; k < nLine; k++, i1+= nInter, i2+= nInter) *i2= *i1; for (k= nLine + by, i2= i0 + (nLine + by) * nInter; k < nLine; k++, i2+= nInter) *i2= val; } } indata += nStep; } } template void shift1d_1(F *in, int nDim, ptrdiff_t *dims, int nVars, int dimension, double by, double val) { if (!by) return; ptrdiff_t nData= DimsProd(nDim, dims, nVars) / dims[dimension]; ptrdiff_t nInter = DimsProd(dimension, dims, nVars); ptrdiff_t nLine= dims[dimension]; ptrdiff_t nStep= nInter * (nLine - 1); F *indata= in; F *i0, *i1, *i2; ptrdiff_t i, j, k, d; double a, p; for(i= 0; i < nData; i+= nInter) { for(j= 0; j < nInter; j++) { i0= indata++; if (by > 0) { d= (ptrdiff_t)floor(by); a= by - d; if (d > nLine) d= nLine; i1= i0 + (nLine - d - 1) * nInter; i2= i0 + (nLine - 1) * nInter; p= *i1; i1-= nInter; for (k= d + 1; k < nLine; k++, i1-= nInter, i2-= nInter) { *i2= a * *i1 + (1.0 - a) * p; p= *i1; } *i2= a * val + (1.0 - a) * p; i2+= nInter; for (k= 1, i2= i0; k < d; k++, i2+= nInter) *i2= val; } else { d= (ptrdiff_t)floor(-by); a= -by - d; if (d > nLine) d= nLine; i1= i0 + d * nInter; i2= i0; p= *i1; i1+= nInter; for (k= d + 1; k < nLine; k++, i1+= nInter, i2+= nInter) { *i2= a * *i1 + (1.0 - a) * p; p= *i1; } *i2= a * val + (1.0 - a) * p; i2+= nInter; for (k= 1, i2= i0 + (nLine - d + 1) * nInter; k < d; k++, i2+= nInter) *i2= val; } } indata += nStep; } } template void Shift1D (Image& I, const int dimension, const double by, double val =0, const resmet method =reslin) { if (!I.data) throw Allocerr(); if (dimension >= I.nDim) throw Argerr(); int j; if (method == reslin) for (j= 0; j < I.nVars; j++) shift1d_1(I.data + j,I.nDim,I.dims,I.nVars,dimension,by/I.Dx(dimension),val); else for (j= 0; j < I.nVars; j++) shift1d_0(I.data + j,I.nDim,I.dims,I.nVars,dimension,(ptrdiff_t)floor(by/I.Dx(dimension)+0.5),val); } //template void Shift2D (Image& I, const double sx, const double sy, // double val =0, const resmet method =reslin) { // Shift1D(I,0,sx,val,method); // Shift1D(I,1,sy,val,method); //} //template void Shift3D (Image& I, const double sx, const double sy, const double sz, // double val =0, const resmet method =reslin) { //TODO speedup resnear // Shift1D(I,0,sx,val,method); // Shift1D(I,1,sy,val,method); // Shift1D(I,2,sz,val,method); //} //Rotations and shifts in 2d***************************************************************************** template void rotate2D_0(F *in, ptrdiff_t width, ptrdiff_t height, ptrdiff_t step, ptrdiff_t stride, double dx, double dy, double x, double y, double sx, double sy, double angle, double val) { F *i0, *i1, *i2, fp; ptrdiff_t i, j, d; double ft, fs, f; ft= -tan(angle / 2.0) * dy / dx; fs= sin(angle) * dx / dy; fp= val; f= - ((y - sy) / dy + height / 2.0) * ft + sx / dx; for (i= 0, i0= in; i < height; i++, i0+= stride, f+= ft) { d= (ptrdiff_t)floor(f + 0.5); if (d > 0) { for (j= d, i1= i0 + (width - d - 1) * step, i2= i0 + (width - 1) * step; j < width; j++, i1-= step, i2-= step) *i2= *i1; if (d > width) d= width; for (j= 0, i2= i0; j < d; j++, i2+= step) *i2= fp; } else if (d < 0) { for (j= - d, i2= i0, i1= i0 - d * step; j < width; j++, i1+= step, i2+= step) *i2= *i1; if (d < - width) d= - width; for (j= width + d, i2= i0 + (width + d) * step; j < width; j++, i2+= step) *i2= fp; } } f= - (x / dx + width / 2.0) * fs + sy / dy; for (i= 0, i0= in; i < width; i++, i0+= step, f+= fs) { d= (ptrdiff_t)floor(f + 0.5); if (d > 0) { for (j= d, i1= i0 + (height - d - 1) * stride, i2= i0 + (height - 1) * stride; j < height; j++, i1-= stride, i2-= stride) *i2= *i1; if (d > height) d= height; for (j= 0, i2= i0; j < d; j++, i2+= stride) *i2= fp; } else if (d < 0) { for (j= - d, i2= i0, i1= i0 - d * stride; j < height; j++, i1+= stride, i2+= stride) *i2= *i1; if (d < - height) d= - height; for (j= height + d, i2= i0 + (height + d) * stride; j < height; j++, i2+= stride) *i2= fp; } } f= - (y / dy + height / 2.0) * ft; for (i= 0, i0= in; i < height; i++, i0+= stride, f+= ft) { d= (ptrdiff_t)floor(f + 0.5); if (d > 0) { for (j= d, i1= i0 + (width - d - 1) * step, i2= i0 + (width - 1) * step; j < width; j++, i1-= step, i2-= step) *i2= *i1; if (d > width) d= width; for (j= 0, i2= i0; j < d; j++, i2+= step) *i2= fp; } else if (d < 0) { for (j= - d, i2= i0, i1= i0 - d * step; j < width; j++, i1+= step, i2+= step) *i2= *i1; if (d < - width) d= - width; for (j= width + d, i2= i0 + (width + d) * step ; j < width; j++, i2+= step) *i2= fp; } } } template void rotate2D_pi(F *in, ptrdiff_t width, ptrdiff_t height, ptrdiff_t step, ptrdiff_t stride) { F *i0, *i1, *i2, *i3, fp; ptrdiff_t i, j, n, num; num= (width * height) / 2; for (i= 0, n= 0, i0= in, i2= in + stride * (height - 1) ; (i < height)&&(n < num); i++, i0+= stride, i2-= stride) for (j= 0, i1= i0, i3= i2 + (width - 1) * step; (j < width)&&(n < num); j++, i1+= step, i3-= step, n++) { fp= *i1; *i1= *i3; *i3= fp; } } template void rotate2D_pi_2(F *in, F *out, ptrdiff_t width, ptrdiff_t height, ptrdiff_t step1, ptrdiff_t step2, ptrdiff_t stride1, ptrdiff_t stride2) { F *i0, *i1, *i2, *i3, fp; ptrdiff_t i, j; for (i= 0, i0= in, i2= out + stride2 * (width - 1) ; i < height; i++, i0+= stride1, i2+= step2) for (j= 0, i1= i0, i3= i2; j < width; j++, i1+= step1, i3-= stride2) *i3= *i1; } template void rotate2D_1(F *in, ptrdiff_t width, ptrdiff_t height, ptrdiff_t step, ptrdiff_t stride, double dx, double dy, double x, double y, double sx, double sy, double angle, double val) { F *i0, *i1, *i2, fp; ptrdiff_t i, j, d; double ft, fs, f, a, p, r; ft= -tan(angle / 2.0) * dy / dx; fs= sin(angle) * dx / dy; fp= val; f= - ((y - sy) / dy + height / 2.0) * ft + sx / dx; for (i= 0, i0= in; i < height; i++, i0+= stride, f+= ft) { if (f > 0) { d= (ptrdiff_t)floor(f); a= f - d; if (d > width) d= width; i1= i0 + (width - d - 1) * step; i2= i0 + (width - 1) * step; p= *i1; i1-= step; for (j= d + 1; j < width; j++, i1-= step, i2-= step) { r= *i1; *i2= a * r + (1.0 - a) * p; p= r; } *i2= (1.0 - a) * p + a * fp; for (j= 0, i2= i0; j < d; j++, i2+= step) *i2= fp; } else if (f < 0) { d= (ptrdiff_t)floor(-f); a= -f - d; if (d > width) d= width; i1= i0 + d * step; i2= i0; p= *i1; i1+= step; for (j= d + 1; j < width; j++, i1+= step, i2+= step) { r= *i1; *i2= a * r + (1.0 - a) * p; p= r; } *i2= (1.0 - a) * p + a * fp; for (j= 0, i2= i0 + (width - d) * step; j < d; j++, i2+= step) *i2= fp; } } f= - (x / dx + width / 2.0) * fs + sy / dy; for (i= 0, i0= in; i < width; i++, i0+= step, f+= fs) { if (f > 0) { d= (ptrdiff_t)floor(f); a= f - d; if (d > height) d= height; i1= i0 + (height - d - 1) * stride; i2= i0 + (height - 1) * stride; p= *i1; i1-= stride; for (j= d + 1; j < height; j++, i1-= stride, i2-= stride) { r= *i1; *i2= a * r + (1 - a) * p; p= r; } *i2= (1.0 - a) * p + a * fp; for (j= 0, i2= i0; j < d; j++, i2+= stride) *i2= fp; } else if (f < 0) { d= (ptrdiff_t)floor(-f); a= -f - d; if (d > height) d= height; i1= i0 + d * stride; i2= i0; p= *i1; i1+= stride; for (j= d + 1; j < height; j++, i1+= stride, i2+= stride) { r= *i1; *i2= a * r + (1 - a) * p; p= r; } *i2= (1.0 - a) * p + a * fp; for (j= 0, i2= i0 + (height - d) * stride; j < d; j++, i2+= stride) *i2= fp; } } f= - (y / dy + height / 2.0) * ft; for (i= 0, i0= in; i < height; i++, i0+= stride, f+= ft) { if (f > 0) { d= (ptrdiff_t)floor(f); a= f - d; if (d > width) d= width; i1= i0 + (width - d - 1) * step; i2= i0 + (width - 1) * step; p= *i1; i1-= step; for (j= d + 1; j < width; j++, i1-= step, i2-= step) { r= *i1; *i2= a * r + (1.0 - a) * p; p= r; } *i2= (1.0 - a) * p + a * fp; for (j= 0, i2= i0; j < d; j++, i2+= step) *i2= fp; } else if (f < 0) { d= (ptrdiff_t)floor(-f); a= -f - d; if (d > width) d= width; i1= i0 + d * step; i2= i0; p= *i1; i1+= step; for (j= d + 1; j < width; j++, i1+= step, i2+= step) { r= *i1; *i2= a * r + (1.0 - a) * p; p= r; } *i2= (1.0 - a) * p + a * fp; for (j= 0, i2= i0 + (width - d) * step; j < d; j++, i2+= step) *i2= fp; } } } //new template void shift2D_0(F *in, ptrdiff_t width, ptrdiff_t height, ptrdiff_t nvar, double dx, double dy, double sx, double sy, double val) { F *i1, *i2, *i3, *i4, fp; ptrdiff_t i, j, ddx, ddy, nwidth, nddx; fp= val; #define COPYLINE \ if (ddx > 0) { \ for (j= nddx, i4= i2 + nwidth - 1, i3= i1 + nwidth - nddx - 1; j < nwidth; j++, i3--, i4--) \ *i4= *i3; \ for (j= 0, i4= i2; j < nddx; j++, i4++) \ *i4= fp; \ } else { \ for (j= - nddx, i4= i2, i3= i1 - nddx; j < nwidth; j++, i3++, i4++) \ *i4= *i3; \ for (j= nwidth + nddx, i4= i2 + nwidth + nddx; j < nwidth; j++, i4++) \ *i4= fp; \ } #define SETLINE \ for (j= 0, i4= i2; j < nwidth; j++, i4++) \ *i4= fp; nwidth= nvar * width; ddx= (ptrdiff_t)floor(sx / dx + 0.5); if (ddx > width) ddx= width; if (ddx < - width) ddx= - width; nddx= nvar * ddx; ddy= (ptrdiff_t)floor(sy / dy + 0.5); if (ddy > height) ddy= height; if (ddy < - height) ddy= - height; if ((ddx == 0)&&(ddy == 0)) return; if (ddy > 0) { for (i= ddy, i1= in + (height - ddy - 1) * nwidth, i2= in + (height - 1) * nwidth; i < height; i++, i1-= nwidth, i2-= nwidth) COPYLINE for (i= 0, i2= in; i < ddy; i++, i2+= nwidth) SETLINE } else { for (i= - ddy, i2= in, i1= in - ddy * nwidth; i < height; i++, i1+= nwidth, i2+= nwidth) COPYLINE for (i= height + ddy, i2= in + (height + ddy) * nwidth; i < height; i++, i2+= nwidth) SETLINE } } template void shift3D_0(F *in, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, ptrdiff_t nvar, double dx, double dy, double dz, double sx, double sy, double sz, double val) { F *i1, *i2, *i3, *i4, fp; ptrdiff_t i, j, k, ddx, ddy, ddz, nwidth, nddx, nsize; fp= val; nwidth= nvar * width; ddx= (ptrdiff_t)floor(sx / dx + 0.5); if (ddx > width) ddx= width; if (ddx < - width) ddx= - width; nddx= nvar * ddx; ddy= (ptrdiff_t)floor(sy / dy + 0.5); if (ddy > height) ddy= height; if (ddy < - height) ddy= - height; ddz= (ptrdiff_t)floor(sz / dz + 0.5); if (ddz > depth) ddz= depth; if (ddz < - depth) ddz= - depth; if ((ddx == 0)&&(ddy == 0)&&(ddz == 0)) return; if (ddz > 0) { if (ddy > 0) { for (k= ddz; k < depth; k++) { for (i= ddy, i1= in + ((depth - k) * height - ddy - 1) * nwidth, i2= in + ((depth - k + ddz) * height - 1) * nwidth; i < height; i++, i1-= nwidth, i2-= nwidth) COPYLINE for (i= 0, i2= in + k * height * nwidth; i < ddy; i++, i2+= nwidth) SETLINE } } else { for (k= ddz; k < depth; k++) { for (i= - ddy, i1= in + ((depth - k - 1) * height - ddy) * nwidth, i2= in + (depth - k + ddz - 1) * height * nwidth; i < height; i++, i1+= nwidth, i2+= nwidth) COPYLINE for (i= height + ddy, i2= in + (k * height - ddy - 1) * nwidth; i < height; i++, i2+= nwidth) SETLINE } } for (k= 0, i2= in; k < ddz; k++) for (i= 0; i < height; i++, i2+= nwidth) SETLINE } else { if (ddy > 0) { for (k= - ddz; k < depth; k++) { for (i= ddy, i2= in + ((k + ddz + 1) * height - 1) * nwidth, i1= in + ((k + 1) * height - ddy - 1) * nwidth; i < height; i++, i1-= nwidth, i2-= nwidth) COPYLINE for (i= height + ddy, i2= in + (k + ddz) * nwidth; i < height; i++, i2+= nwidth) SETLINE } } else { for (k= - ddz; k < depth; k++) { for (i= - ddy, i2= in + (k + ddz) * height * nwidth, i1= in + (k * height - ddy) * nwidth; i < height; i++, i1+= nwidth, i2+= nwidth) COPYLINE for (i= height + ddy, i2= in + ((k + ddz + 1) * height + ddy - 1) * nwidth; i < height; i++, i2+= nwidth) SETLINE } } for (k= depth + ddz, i2= in + (depth + ddz - 1) * height * nwidth ; k < depth; k++) for (i= 0; i < height; i++, i2+= nwidth) SETLINE } #undef COPYLINE #undef SETLINE } template void shift2D_1(F *in, ptrdiff_t width, ptrdiff_t height, ptrdiff_t step, double dx, double dy, double sx, double sy, double val) { F *i0, *i1, *i2, fp; ptrdiff_t i, j, d; double a, f, p, r; fp= val; f= sx / dx; for (i= 0, i0= in; i < height; i++, i0+= width * step) { if (f > 0) { d= (ptrdiff_t)floor(f); a= f - d; if (d > width) d= width; i1= i0 + (width - d - 1) * step; i2= i0 + (width - 1) * step; p= *i1; i1-= step; for (j= d + 1; j < width; j++, i1-= step, i2-= step) { r= *i1; *i2= a * r + (1.0 - a) * p; p= r; } *i2= a * val + (1.0 - a) * p; for (j= 0, i2= i0; j < d; j+= step, i2+= step) *i2= fp; } else if (f < 0) { d= (ptrdiff_t)floor(-f); a= -f - d; if (d > width) d= width; i1= i0 + d * step; i2= i0; p= *i1; i1+= step; for (j= d + 1; j < width; j++, i1+= step, i2+= step) { r= *i1; *i2= a * r + (1.0 - a) * p; p= r; } *i2= a * val + (1.0 - a) * p; for (j= 0, i2= i0 + (width - d); j < d; j++, i2+= step) *i2= fp; } } f= sy / dy; for (i= 0, i0= in; i < width; i++, i0+= step) { if (f > 0) { d= (ptrdiff_t)floor(f); a= f - d; if (d > height) d= height; i1= i0 + (height - d - 1) * width * step; i2= i0 + (height - 1) * width * step; p= *i1; i1-= width * step; for (j= d + 1; j < height; j++, i1-= width * step, i2-= width * step) { r= *i1; *i2= a * r + (1 - a) * p; p= r; } *i2= a * val + (1.0 - a) * p; for (j= 0, i2= i0; j < d; j++, i2+= width * step) *i2= fp; } else if (f < 0) { d= (ptrdiff_t)floor(-f); a= -f - d; if (d > height) d= height; i1= i0 + d * width * step; i2= i0; p= *i1; i1+= width * step; for (j= d + 1; j < height; j++, i1+= width * step, i2+= width * step) { r= *i1; *i2= a * r + (1 - a) * p; p= r; } *i2= a * val + (1.0 - a) * p; for (j= 0, i2= i0 + (height - d) * width; j < d; j++, i2+= width * step) *i2= fp; } } } template void Shift2D (Image& I, const double sx, const double sy, double val= 0, resmet method = reslin) { F* p; if (I.nDim < 2) throw Dimserr(); if (!I.data) throw Allocerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t slisize= DimsProd(2, I.dims, I.nVars); ptrdiff_t i, j; for (i= 0, p= I.data; i < numslic; i++, p+= slisize) if (method == reslin) for (j= 0; j < I.nVars; j++) shift2D_1(p + j, I.dims[0], I.dims[1], I.nVars, I.Dx(0), I.Dx(1), sx, sy, val); else shift2D_0(p, I.dims[0], I.dims[1], I.nVars, I.Dx(0), I.Dx(1), sx, sy, val); } //new template void Shift3D (Image& I, const double sx, const double sy, const double sz, double val =0, const resmet method =reslin) { if (method == resnear) { F* p; if (I.nDim < 3) throw Dimserr(); if (!I.data) throw Allocerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t slisize= DimsProd(3, I.dims, I.nVars); ptrdiff_t i, j; for (i= 0, p= I.data; i < numslic; i++, p+= slisize) shift3D_0(p, I.dims[0], I.dims[1], I.dims[2], I.nVars, I.Dx(0), I.Dx(1), I.Dx(2), sx, sy, sz, val); } else { Shift1D(I,0,sx,val,method); Shift1D(I,1,sy,val,method); Shift1D(I,2,sz,val,method); } } template void Rot2D (Image& I, const double dx, const double dy, const double sx, const double sy, const double angle, double val= 0, resmet method = reslin) { F* p; if (I.nDim < 2) throw Dimserr(); if (!I.data) throw Allocerr(); if ((angle > M_PI_2)||(angle < -M_PI_2)) throw Valerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t slisize= DimsProd(2, I.dims, I.nVars); ptrdiff_t i, j; for (i= 0, p= I.data; i < numslic; i++, p+= slisize) if (method == reslin) for (j= 0; j < I.nVars; j++) rotate2D_1(p + j, I.dims[0], I.dims[1], I.nVars, I.dims[0]*I.nVars, I.Dx(0), I.Dx(1), dx, dy, sx, sy, angle, val); else for (j= 0; j < I.nVars; j++) rotate2D_0(p + j, I.dims[0], I.dims[1], I.nVars, I.dims[0]*I.nVars, I.Dx(0), I.Dx(1), dx, dy, sx, sy, angle, val); } template void Rot2DPi (Image& I) { F* p; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t slisize= DimsProd(2, I.dims, I.nVars); ptrdiff_t i, j, k; ptrdiff_t numplane, plstep, step, stride; stride= I.dims[0] * I.nVars; for (i= 0, p= I.data; i < numslic; i++, p+= slisize) for (k= 0; k < I.nVars; k++) rotate2D_pi(p + k, I.dims[0], I.dims[1], I.nVars, stride); } template Image * Rot2DPi2 (Image& I) { F *p, *q; ptrdiff_t i, j, k; Image *O; ptrdiff_t *dims= new ptrdiff_t[I.nDim]; dims[0]= I.dims[1]; dims[1]= I.dims[0]; for (i= 2; i < I.nDim; i++) dims[i]= I.dims[i]; double *bounds= new double[2*I.nDim]; bounds[0]= I.bounds[2]; bounds[1]= I.bounds[3]; bounds[2]= I.bounds[0]; bounds[3]= I.bounds[1]; O= new Image(I.nDim,dims,bounds,I.nVars); O->NewData(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t slisize= DimsProd(2, I.dims, I.nVars); ptrdiff_t stride1, stride2; stride1= I.dims[0] * I.nVars; stride2= I.dims[1] * I.nVars; for (i= 0, p= I.data, q= O->data; i < numslic; i++, p+= slisize, q+= slisize) for (k= 0; k < I.nVars; k++) rotate2D_pi_2(p + k, q + k, I.dims[0], I.dims[1], I.nVars, I.nVars, stride1, stride2); delete[] bounds; delete[] dims; return O; } template Image * Rot2Df (Image& I, const double dx, const double dy, const double sx, const double sy, const double angle, double val= 0, resmet method = reslin) { if (I.nDim < 2) throw Dimserr(); if (!I.data) throw Allocerr(); double angle1= angle - floor(0.5 * angle / M_PI + 0.125) * 2. * M_PI; //-pi/4 to 7/4pi double a= angle1 + M_PI * 0.25; Image *O; if (a < M_PI_2) { O= new Image(I); O->NewData(); O->SetData(I.data); Rot2D (*O, dx, dy, sx, sy, angle1, val, method); } else if (a < M_PI) { O= Rot2DPi2(I); Rot2D (*O, -dy, dx, -sy, sx, angle1 - M_PI_2, val, method); } else if (a < 3 * M_PI_2) { O= new Image(I); O->NewData(); O->SetData(I.data); Rot2DPi(*O); Rot2D (*O, -dx, -dy, -sx, -sy, angle1 - M_PI, val, method); } else { O= Rot2DPi2(I); Rot2DPi(*O); Rot2D (*O, dy, -dx, sy, -sx, angle1 - 3. * M_PI_2, val, method); } return O; } template void Rot3DPlane (Image& I, const int plane, const double dx, const double dy, const double sx, const double sy, const double angle, double val= 0, resmet method = reslin) { F* p; F* q; if (I.nDim < 3) throw Dimserr(); // if (I.nVars!=1) throw NVarerr(); if (!I.data) throw Allocerr(); if ((angle > M_PI_2)||(angle < -M_PI_2)) throw Valerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t slisize= DimsProd(3, I.dims); ptrdiff_t i, j, k; ptrdiff_t dimx, dimy, numplane, plstep, step, stride; double calx, caly; switch (plane) { case 0: //xy dimx= I.dims[0]; dimy= I.dims[1]; calx= I.Dx(0); caly= I.Dx(1); numplane= I.dims[2]; plstep= I.dims[0] * I.dims[1] * I.nVars; step= I.nVars; stride= I.dims[0] * I.nVars; break; case 1: //xz dimx= I.dims[0]; dimy= I.dims[2]; calx= I.Dx(0); caly= I.Dx(2); numplane= I.dims[1]; plstep= I.dims[0] * I.nVars; step= I.nVars; stride= I.dims[0] * I.dims[1] * I.nVars; break; case 2: //zy dimx= I.dims[2]; dimy= I.dims[1]; calx= I.Dx(2); caly= I.Dx(1); numplane= I.dims[0]; plstep= I.nVars; step= I.dims[0] * I.dims[1] * I.nVars; stride= I.dims[0] * I.nVars; break; default: throw Valerr(); } for (i= 0, p= I.data; i < numslic; i++, p+= slisize) for (j= 0, q= p; j < numplane; j++, q+= plstep) if (method == reslin) for (k= 0; k < I.nVars; k++) rotate2D_1(q + k, dimx, dimy, step, stride, calx, caly, dx, dy, sx, sy, angle, val); else for (k= 0; k < I.nVars; k++) rotate2D_0(q + k, dimx, dimy, step, stride, calx, caly, dx, dy, sx, sy, angle, val); } template void Rot3DPlanePi (Image& I, const int plane) { F* p; F* q; if (I.nDim < 3) throw Dimserr(); // if (I.nVars!=1) throw NVarerr(); if (!I.data) throw Allocerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t slisize= DimsProd(3, I.dims); ptrdiff_t i, j, k; ptrdiff_t dimx, dimy, numplane, plstep, step, stride; switch (plane) { case 0: //xy dimx= I.dims[0]; dimy= I.dims[1]; numplane= I.dims[2]; plstep= I.dims[0] * I.dims[1] * I.nVars; step= I.nVars; stride= I.dims[0] * I.nVars; break; case 1: //xz dimx= I.dims[0]; dimy= I.dims[2]; numplane= I.dims[1]; plstep= I.dims[0] * I.nVars; step= I.nVars; stride= I.dims[0] * I.dims[1] * I.nVars; break; case 2: //zy dimx= I.dims[2]; dimy= I.dims[1]; numplane= I.dims[0]; plstep= I.nVars; step= I.dims[0] * I.dims[1] * I.nVars; stride= I.dims[0] * I.nVars; break; default: throw Valerr(); } for (i= 0, p= I.data; i < numslic; i++, p+= slisize) for (j= 0, q= p; j < numplane; j++, q+= plstep) for (k= 0; k < I.nVars; k++) rotate2D_pi(q + k, dimx, dimy, step, stride); } //Morphology gray in 2D and 3D******************************************************************* template inline F max2(const F& a, const F& b) { if (a > b) return a; return b; } template inline F min2(const F& a, const F& b) { if (a < b) return a; return b; } template inline F max3(const F& a, const F& b, const F& c) { if (a > b) { if (a > c) return a; } else { if (b > c) return b; } return c; } template inline F min3(const F& a, const F& b, const F& c) { if (a < b) { if (a < c) return a; } else { if (b < c) return b; } return c; } template void dilate1D_0 (F *in, ptrdiff_t width, F *out) { F *i0, *o, s1; ptrdiff_t j; o= out; *i0= in; *(o++)= *i0; for(j= 1; j < width; j++) { s1= *i0; i0++; *(o++)= max2(s1, *i0); } } template void erode1D_1 (F *in, ptrdiff_t width, F *out) { F *i0, *o, s1; ptrdiff_t j; o= out; *i0= in; *(o++)= *i0; for(j= 1; j < width; j++) { s1= *i0; i0++; *(o++)= min2(s1, *i0); } } template void erode1D_0 (F *in, ptrdiff_t width, F *out) { F *i0, *o, s1; ptrdiff_t j; o= out; *i0= in; for(j= 1; j < width; j++) { s1= *i0; i0++; *(o++)= min2(s1, *i0); } *(o++)= *i0; } template void dilate1D_2 (F *in, ptrdiff_t width, F *out) { F *i0, *o, s1, s2; ptrdiff_t j; o= out; *i0= in; s1= *i0; i0++; *(o++)= max2(s1, *i0); for(j= 2; j < width; j++) { s2= s1; s1= *i0; i0++; *(o++)= max3(s2, s1, *i0); \ } *(o++)= max2(s1, *i0); } template void erode1D_2 (F *in, ptrdiff_t width, F *out) { F *i0, *o, s1, s2; ptrdiff_t j; o= out; *i0= in; s1= *i0; i0++; *(o++)= min2(s1, *i0); for(j= 2; j < width; j++) { s2= s1; s1= *i0; i0++; *(o++)= min3(s2, s1, *i0); \ } *(o++)= min2(s1, *i0); } template void dilate2D_0 (F *in, ptrdiff_t width, ptrdiff_t height, F *out) { F *i0, *i1, *o, s1, s2; ptrdiff_t i, j; #define VYP \ s1= max2(*i0, *i1); \ *(o++)= s1; \ for(j= 1; j < width; j++) { \ s2= s1; \ i0++; i1++; \ s1= max2(*i0, *i1); \ *(o++)= max2(s1, s2); \ } \ i0++; i1++; o= out; i0= in; i1= i0; VYP i0= in; for(i= 1; i < height; i++) { VYP } #undef VYP } template void erode2D_1 (F *in, ptrdiff_t width, ptrdiff_t height, F *out) { F *i0, *i1, *o, s1, s2; ptrdiff_t i, j; #define VYP \ s1= min2(*i0, *i1); \ *(o++)= s1; \ for(j= 1; j < width; j++) { \ s2= s1; \ i0++; i1++; \ s1= min2(*i0, *i1); \ *(o++)= min2(s1, s2); \ } \ i0++; i1++; o= out; i0= in; i1= i0; VYP i0= in; for(i= 1; i < height; i++) { VYP } #undef VYP } template void erode2D_0 (F *in, ptrdiff_t width, ptrdiff_t height, F *out) { F *i0, *i1, *o, s1, s2; ptrdiff_t i, j; #define VYP \ s1= min2(*i0, *i1); \ for(j= 1; j < width; j++) { \ s2= s1; \ i0++; i1++; \ s1= min2(*i0, *i1); \ *(o++)= min2(s1, s2); \ } \ i0++; i1++; \ *(o++)= s1; o= out; \ i0= in; i1= i0 + width; for(i= 1; i < height; i++) { VYP } i1= i0; VYP #undef VYP } #define VYP4(fnc2, fnc3) \ sp= *i0; \ s2= fnc3(*i0, *i1, *i2); \ i0++; i1++; i2++; \ s1= *i0; \ *(o++)= fnc2(s1, s2); \ for(j= 2; j < width; j++) { \ s3= sp; \ sp= s1; \ s2= fnc3(*i0, *i1, *i2); \ i0++; i1++; i2++; \ s1= *i0; \ *(o++)= fnc3(s1, s2, s3); \ } \ s2= fnc3(*i0, *i1, *i2); \ i0++; i1++; i2++; \ *(o++)= fnc2(s2, sp); #define DO4(fnc2, fnc3) \ o= out; \ i0= in; i2= in; i1= in + width; \ VYP4(fnc2, fnc3) \ i2= in; \ for(i= 2; i < height; i++) {\ VYP4(fnc2, fnc3) \ } \ i1= i0; \ VYP4(fnc2, fnc3) template void dilate2D_4 (F *in, ptrdiff_t width, ptrdiff_t height, F *out) { F *i0, *i1, *i2, *o, s1, s2, s3, sp; ptrdiff_t i, j; DO4(max2, max3) } template void erode2D_4 (F *in, ptrdiff_t width, ptrdiff_t height, F *out) { F *i0, *i1, *i2, *o, s1, s2, s3, sp; ptrdiff_t i, j; DO4(min2, min3) } #undef VYP4 #undef DO4 #define VYP8(fnc2, fnc3) \ s2= fnc3(*i0, *i1, *i2); \ i0++; i1++; i2++; \ s1= fnc3(*i0, *i1, *i2); \ *(o++)= fnc2(s1, s2); \ for(j= 2; j < width; j++) { \ s3= s2; \ s2= s1; \ i0++; i1++; i2++; \ s1= fnc3(*i0, *i1, *i2); \ *(o++)= fnc3(s1, s2, s3); \ } \ i0++; i1++; i2++; \ *(o++)= fnc2(s1, s2); #define DO8(fnc2, fnc3) \ o= out; \ i0= in; i2= in; i1= in + width; \ VYP8(fnc2, fnc3) \ i2= in; \ for(i= 2; i < height; i++) {\ VYP8(fnc2, fnc3) \ } \ i1= i0; \ VYP8(fnc2, fnc3) template void dilate2D_8 (F *in, ptrdiff_t width, ptrdiff_t height, F *out) { F *i0, *i1, *i2, *o, s1, s2, s3; ptrdiff_t i, j; DO8(max2, max3) } template void erode2D_8 (F *in, ptrdiff_t width, ptrdiff_t height, F *out) { F *i0, *i1, *i2, *o, s1, s2, s3; ptrdiff_t i, j; DO8(min2, min3) } #undef VYP8 #undef DO8 template void dilate3D_0 (F *in, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, F *out) { F *i00, *i01, *i10, *i11, *o, s1, s2; ptrdiff_t i, j, k, size; size= width * height; #define VYP2 \ s1= max2(*i00, *i01); \ s1= max3(s1, *i10, *i11); \ *(o++)= s1; \ for(k= 1; k < width; k++) { \ s2= s1; \ i00++; i01++; i10++; i11++; \ s1= max2(*i00, *i01); \ s1= max3(s1, *i10, *i11); \ *(o++)= max2(s1, s2); \ } \ i00++; i01++; i10++; i11++; #define VYP1 \ i00= i10; i01= i11; \ VYP2 \ i00= i10 - width; i01= i11 - width; \ for(j= 1; j < height; j++) { \ VYP2 \ } o= out; i11= in; i10= i11; VYP1 i10= in; for(i= 1; i < depth; i++) { VYP1 } #undef VYP1 #undef VYP2 } template void erode3D_1 (F *in, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, F *out) { F *i00, *i01, *i10, *i11, *o, s1, s2; ptrdiff_t i, j, k, size; size= width * height; #define VYP2 \ s1= min2(*i00, *i01); \ s1= min3(s1, *i10, *i11); \ *(o++)= s1; \ for(k= 1; k < width; k++) { \ s2= s1; \ i00++; i01++; i10++; i11++; \ s1= min2(*i00, *i01); \ s1= min3(s1, *i10, *i11); \ *(o++)= min2(s1, s2); \ } \ i00++; i01++; i10++; i11++; #define VYP1 \ i00= i10; i01= i11; \ VYP2 \ i00= i10 - width; i01= i11 - width; \ for(j= 1; j < height; j++) { \ VYP2 \ } o= out; i11= in; i10= i11; VYP1 i10= in; for(i= 1; i < depth; i++) { VYP1 } #undef VYP1 #undef VYP2 } template void erode3D_0 (F *in, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, F *out) { F *i00, *i01, *i10, *i11, *o, s1, s2; ptrdiff_t i, j, k, size; size= width * height; #define VYP2 \ s1= min2(*i00, *i01); \ s1= min3(s1, *i10, *i11); \ for(k= 1; k < width; k++) { \ s2= s1; \ i00++; i01++; i10++; i11++; \ s1= min2(*i00, *i01); \ s1= min3(s1, *i10, *i11); \ *(o++)= min2(s1, s2); \ } \ i00++; i01++; i10++; i11++; \ *(o++)= s1; #define VYP1 \ i01= i00 + width; i11= i10 + width; \ for(j= 1; j < height; j++) { \ VYP2 \ } \ i01= i00; i11= i10; \ VYP2 o= out; i00= in; i10= i00 + size; for(i= 1; i < depth; i++) { VYP1 } i10= i00; VYP1 #undef VYP1 #undef VYP2 } #define VYP2(fnc2, fnc3) \ sp= fnc3(*i00, *i01, *i02); \ sp= fnc3(sp, *i10, *i20); \ s2= fnc3(sp, *i11, *i12); \ s2= fnc3(s2, *i21, *i22); \ i00++; i01++; i02++; \ i10++; i11++; i12++; \ i20++; i21++; i22++; \ s1= fnc3(*i00, *i01, *i02); \ s1= fnc3(s1, *i10, *i20); \ *(o++)= fnc2(s1, s2); \ for(k= 2; k < width; k++) { \ s3= sp; \ sp= s1; \ s2= fnc3(sp, *i11, *i12); \ s2= fnc3(s2, *i21, *i22); \ i00++; i01++; i02++; \ i10++; i11++; i12++; \ i20++; i21++; i22++; \ s1= fnc3(*i00, *i01, *i02); \ s1= fnc3(s1, *i10, *i20); \ *(o++)= fnc3(s1, s2, s3); \ } \ s2= fnc3(sp, *i11, *i12); \ s2= fnc3(s2, *i21, *i22); \ i00++; i01++; i02++; \ i10++; i11++; i12++; \ i20++; i21++; i22++; \ *(o++)= fnc2(sp, s2); #define VYP1(fnc2, fnc3) \ i01= i00 + width; i11= i10 + width; i21= i20 + width; \ i02= i00; i12= i10; i22= i20; \ VYP2(fnc2, fnc3) \ i02= i00 - width; i12= i10 - width; i22= i20 - width; \ for(j= 2; j < height; j++) { \ VYP2(fnc2, fnc3) \ } \ i01= i00; i11= i10; i21= i20; \ VYP2(fnc2, fnc3) #define DO18(fnc2, fnc3) \ o= out; \ i00= in; \ i10= i00 + size; \ i20= i00; \ VYP1(fnc2, fnc3) \ i20= in; \ for(i= 2; i < depth; i++) { \ VYP1(fnc2, fnc3) \ } \ i10= i00; \ VYP1(fnc2, fnc3) \ template void dilate3D_18 (F *in, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, F *out) { F *i00, *i01, *i02, *i10, *i11, *i12, *i20, *i21, *i22, *o, s1, s2, s3, sp; ptrdiff_t i, j, k, size; size= width * height; DO18(max2, max3) } template void erode3D_18 (F *in, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, F *out) { F *i00, *i01, *i02, *i10, *i11, *i12, *i20, *i21, *i22, *o, s1, s2, s3, sp; ptrdiff_t i, j, k, size; size= width * height; DO18(min2, min3) } #undef VYP1 #undef VYP2 #undef DO18 template void dilate3D_lin_z (F* src, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, int n, F* buf) { ptrdiff_t i, j, k, l; ptrdiff_t Ssize= width * height; ptrdiff_t size= Ssize * depth; F *p, *q, *r, *s, *t, *u, *v; if (n < 1) return; memcpy(buf, src, size * sizeof(F)); //forward for (j= 1, r= src + Ssize, k= 1; j < depth; j++, r+= Ssize) { if (k > n) k= 1; else { for (l= 0, t= r, u= r - Ssize; l < height; l++, t+= width, u+= width) for (i= 0, p= t, q= u; i < width; i++, p++, q++) if (*p < *q) *p= *q; k++; } } //backward r= buf + Ssize * (depth - 2); k= (depth - 1) % (n + 1); for (j= 1; j < depth; j++, r-= Ssize) { if (k < 1) k= n; else { for (l= 0, t= r, u= r + Ssize; l < height; l++, t+= width, u+= width) for (i= 0, p= t, q= u; i < width; i++, p++, q++) if (*p < *q) *p= *q; k--; } } //join forward int np= n - n / 2; int nr= n - np; for (j= n, s= buf; j < depth; j++, s+= Ssize) { //TODO optimize for (l= 0, t= s, u= src + Ssize * (j - nr), v= src + Ssize * j; l < height; l++, t+= width, u+= width, v+= width) for (i= 0, p= t, q= u, r= v; i < width; i++, p++, q++, r++) if (*p < *r) *q= *r; else *q= *p; } } template void erode3D_lin_z (F* src, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, int n, F* buf) { ptrdiff_t i, j, k, l; ptrdiff_t Ssize= width * height; ptrdiff_t size= Ssize * depth; F *p, *q, *r, *s, *t, *u, *v; if (n < 1) return; memcpy(buf, src, size * sizeof(F)); //forward for (j= 1, r= src + Ssize, k= 1; j < depth; j++, r+= Ssize) { if (k > n) k= 1; else { for (l= 0, t= r, u= r - Ssize; l < height; l++, t+= width, u+= width) for (i= 0, p= t, q= u; i < width; i++, p++, q++) if (*p > *q) *p= *q; k++; } } //backward r= buf + Ssize * (depth - 2); k= (depth - 1) % (n + 1); for (j= 1; j < depth; j++, r-= Ssize) { if (k < 1) k= n; else { for (l= 0, t= r, u= r + Ssize; l < height; l++, t+= width, u+= width) for (i= 0, p= t, q= u; i < width; i++, p++, q++) if (*p > *q) *p= *q; k--; } } //join forward int nr= n - n / 2; int np= n - nr; for (j= n, s= buf; j < depth; j++, s+= Ssize) { //TODO optimize for (l= 0, t= s, u= src + Ssize * (j - nr), v= src + Ssize * j; l < height; l++, t+= width, u+= width, v+= width) for (i= 0, p= t, q= u, r= v; i < width; i++, p++, q++, r++) if (*p > *r) *q= *r; else *q= *p; } } template void Dilate1D(Image& I, int num) { //TODO van Herk algorithm ptrdiff_t i, j; F *q, *pdat; if (!I.data) throw Allocerr(); if (1 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 1, I.dims + 1); ptrdiff_t step= I.dims[0]; q= I.data; pdat= new F[step]; for (i= 0; i < numslic; i++) { if (num == 1) { memcpy(pdat, q, step * sizeof(F)); dilate1D_0 (pdat, I.dims[0], q); } else for (j= 1; j < num; j++) { memcpy(pdat, q, step * sizeof(F)); dilate1D_2 (pdat, I.dims[0], q); } q+= step; } delete [] pdat; } template void Erode1D(Image& I, int num) { //TODO van Herk algorithm ptrdiff_t i, j; F *q, *pdat; if (!I.data) throw Allocerr(); if (1 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 1, I.dims + 1); ptrdiff_t step= I.dims[0]; q= I.data; pdat= new F[step]; for (i= 0; i < numslic; i++) { if (num == 1) { memcpy(pdat, q, step * sizeof(F)); erode1D_0 (pdat, I.dims[0], I.dims[1], q); } else for (j= 1; j < num; j++) { memcpy(pdat, q, step * sizeof(F)); erode1D_2 (pdat, I.dims[0], I.dims[1], q); } q+= step; } delete [] pdat; } template void MorphGrad1D(Image& I) { ptrdiff_t i, j; F *q, *pdat, *qdat, *r; if (!I.data) throw Allocerr(); if (1 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t numslic= DimsProd(I.nDim - 1, I.dims + 1); ptrdiff_t step= I.dims[0]; q= I.data; pdat= new F[step]; qdat= new F[step]; for (i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(F)); memcpy(qdat, q, step * sizeof(F)); dilate1D_0 (pdat, I.dims[0], I.dims[1], q); erode1D_1 (qdat, I.dims[0], I.dims[1], pdat); for (j= 0, r= pdat; j < step; j++, r++, q++) *q-= *r; } delete [] pdat; delete [] qdat; } template void Close1D(Image& I, int num) { Dilate1D(I, num); Erode1D(I, num); } template void Open1D(Image& I, int num) { Erode1D(I, num); Dilate1D(I, num); } template void Dilate2D(Image& I, int num) { ptrdiff_t i, j; F *q, *pdat; if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; q= I.data; pdat= new F[step]; for (i= 0; i < numslic; i++) { if (num == 1) { memcpy(pdat, q, step * sizeof(F)); dilate2D_0 (pdat, I.dims[0], I.dims[1], q); } else for (j= 1; j < num; j++) { memcpy(pdat, q, step * sizeof(F)); if ((j % 3) == 2) dilate2D_8 (pdat, I.dims[0], I.dims[1], q); else dilate2D_4 (pdat, I.dims[0], I.dims[1], q); } q+= step; } delete [] pdat; } template void Erode2D(Image& I, int num) { ptrdiff_t i, j; F *q, *pdat; if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; q= I.data; pdat= new F[step]; for (i= 0; i < numslic; i++) { if (num == 1) { memcpy(pdat, q, step * sizeof(F)); erode2D_0 (pdat, I.dims[0], I.dims[1], q); } else for (j= 1; j < num; j++) { memcpy(pdat, q, step * sizeof(F)); if ((j % 3) == 2) erode2D_8 (pdat, I.dims[0], I.dims[1], q); else erode2D_4 (pdat, I.dims[0], I.dims[1], q); } q+= step; } delete [] pdat; } template void MorphGrad2D(Image& I) { ptrdiff_t i, j; F *q, *pdat, *qdat, *r; if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; q= I.data; pdat= new F[step]; qdat= new F[step]; for (i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(F)); memcpy(qdat, q, step * sizeof(F)); dilate2D_0 (pdat, I.dims[0], I.dims[1], q); erode2D_1 (qdat, I.dims[0], I.dims[1], pdat); for (j= 0, r= pdat; j < step; j++, r++, q++) *q-= *r; } delete [] pdat; delete [] qdat; } template void Close2D(Image& I, int num) { Dilate2D(I, num); Erode2D(I, num); } template void Open2D(Image& I, int num) { Erode2D(I, num); Dilate2D(I, num); } template void Dilate3D(Image& I, int num) { ptrdiff_t i, j; F *q, *pdat; if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; pdat= new F[step]; for (i= 0; i < numslic; i++) { if (num == 1) { memcpy(pdat, q, step * sizeof(F)); dilate3D_0 (pdat, I.dims[0], I.dims[1], I.dims[2], q); } else for (j= 1; j < num; j++) { memcpy(pdat, q, step * sizeof(F)); dilate3D_18 (pdat, I.dims[0], I.dims[1], I.dims[2], q); } q+= step; } delete [] pdat; } template void Erode3D(Image& I, int num) { ptrdiff_t i, j; F *q, *pdat; if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; pdat= new F[step]; for (i= 0; i < numslic; i++) { if (num == 1) { memcpy(pdat, q, step * sizeof(F)); erode3D_0 (pdat, I.dims[0], I.dims[1], I.dims[2], q); } else for (j= 1; j < num; j++) { memcpy(pdat, q, step * sizeof(F)); erode3D_18 (pdat, I.dims[0], I.dims[1], I.dims[2], q); } q+= step; } delete [] pdat; } template void MorphGrad3D(Image& I) { ptrdiff_t i, j; F *q, *pdat, *qdat, *r; if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; pdat= new F[step]; qdat= new F[step]; for (i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(F)); memcpy(qdat, q, step * sizeof(F)); dilate3D_0 (pdat, I.dims[0], I.dims[1], I.dims[2], q); erode3D_1 (qdat, I.dims[0], I.dims[1], I.dims[2], pdat); for (j= 0, r= pdat; j < step; j++, r++, q++) *q-= *r; } delete [] pdat; delete [] qdat; } template void Close3D(Image& I, int num) { Dilate3D(I, num); Erode3D(I, num); } template void Open3D(Image& I, int num) { Erode3D(I, num); Dilate3D(I, num); } template void Dilate3DLin_z(Image& I, int num) { ptrdiff_t i; F *q, *pdat; if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; Image pImg(3,I.dims); pdat= new F[step]; for (i= 0; i < numslic; i++) { dilate3D_lin_z (q, I.dims[0], I.dims[1], I.dims[2], num, pdat); q+= step; } delete [] pdat; } template void Erode3DLin_z(Image& I, int num) { ptrdiff_t i; F *q, *pdat; if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; Image pImg(3,I.dims); ptrdiff_t dims2[3]= {I.dims[0], I.dims[1], I.dims[2]+2*num}; pdat= new F[step]; for (i= 0; i < numslic; i++) { erode3D_lin_z (q, I.dims[0], I.dims[1], I.dims[2], num, pdat); q+= step; } delete [] pdat; } template void Dilate2D3D(Image& I, int num2, int num3) { Dilate2D(I, num2); Dilate3D(I, num3); } template void Erode2D3D(Image& I, int num2, int num3) { Erode3D(I, num3); Erode2D(I, num2); } template void Close2D3D(Image& I, int num2, int num3) { Dilate2D(I, num2); Dilate3D(I, num3); Erode3D(I, num3); Erode2D(I, num2); } template void Open2D3D(Image& I, int num2, int num3) { Erode2D(I, num2); Erode3D(I, num3); Dilate3D(I, num3); Dilate2D(I, num2); } template void Dilate1D3D(Image& I, int num2, int num3) { Dilate3DLin_z(I, num2); Dilate3D(I, num3); } template void Erode1D3D(Image& I, int num2, int num3) { Erode3D(I, num3); Erode3DLin_z(I, num2); } template void Close1D3D(Image& I, int num2, int num3) { Dilate3DLin_z(I, num2); Dilate3D(I, num3); Erode3D(I, num3); Erode3DLin_z(I, num2); } template void Open1D3D(Image& I, int num2, int num3) { Erode3DLin_z(I, num2); Erode3D(I, num3); Dilate3D(I, num3); Dilate3DLin_z(I, num2); } //Linear morphology #define rot0 0 #define rot90 1 template void getlinpar2d(int num, double angle, int&n1, int&n2, int& rot, double& di) { double v1, v2; if (angle > (M_PI_2)) angle-= M_PI; v1= cos(angle); v2= sin(angle); if (v1 < 0.0) { v1= -v1; v2= -v2; } if (v1 >= sqrt(0.5)) { di= v2 / v1; rot= rot0; } else { di= v1 / v2; rot= rot90; } if (di > 1.0) di= 1.0; if (di < -1.0) di= -1.0; n1= (int)floor(num / hypot(1.0,di)+0.5); n2= (int)floor(fabs(di) * num / hypot(1.0,di)+0.5); } template void dilate2D_lin (F* src, ptrdiff_t width, ptrdiff_t height, int n, int rot, double di, F *buf) { ptrdiff_t i, j, k; ptrdiff_t size= width * height; F *p, *q, *r; double dd; if (n < 1) return; memcpy(buf, src, size * sizeof(F)); switch(rot) { case rot0: { //forward for (j= 1, r= src + 1, dd= di, k= 1; j < width; j++, dd+= di, r++) { if (dd >= 0.5) { dd-= 1.0; i= 1; p= r + width; q= r - 1; } else if (dd < -0.5) { dd+= 1.0; i= 1; p= r; q= r - 1 + width; } else { i= 0; p= r; q= r - 1; } if (k > n) k= 1; else { for (; i < height; i++, p+= width, q+= width) if (*p < *q) *p= *q; k++; } } //backward r= buf + width - 2; dd-= 2.0 * di; k= (width - 1) % (n + 1); for (j= 1; j < width; j++, dd-= di, r--) { if (dd >= 0.5) { dd-= 1.0; i= 1; p= r + width; q= r + 1; } else if (dd < -0.5) { dd+= 1.0; i= 1; p= r; q= r + 1 + width; } else { i= 0; p= r; q= r + 1; } if (k < 1) k= n; else { for (; i < height; i++, p+= width, q+= width) if (*p < *q) *p= *q; k--; } } //join forward double dd1, dd2; int np= n - n / 2; int nr= n - np; dd1= 0.0; dd= np * di; dd2= n * di; for (j= n; j < width; j++, dd1+= di, dd+= di, dd2+= di) { //TODO optimize ptrdiff_t n0; if (di < 0) { n0= ptrdiff_t(floor(dd2+0.5)); q= src + j - nr + width * (ptrdiff_t(floor(dd+0.5)) - n0); i= ptrdiff_t(floor(dd1+0.5)) - n0; r= buf + j - n + i * width; p= src + j; } else { n0= ptrdiff_t(floor(dd1+0.5)); q= src + j - nr + width * (ptrdiff_t(floor(dd+0.5)) - n0); i= ptrdiff_t(floor(dd2+0.5)) - n0; p= src + j + i * width; r= buf + j - n; } for (; i < height; i++, p+= width, q+= width, r+= width) if (*p < *r) *q= *r; else *q= *p; } } break; case rot90: { //forward for (j= 1, r= src + width, dd= di, k= 1; j < height; j++, dd+= di, r+= width) { if (dd >= 0.5) { dd-= 1.0; i= 1; p= r + 1; q= r - width; } else if (dd < -0.5) { dd+= 1.0; i= 1; p= r; q= r - width + 1; } else { i= 0; p= r; q= r - width; } if (k > n) k= 1; else { for (; i < width; i++, p++, q++) if (*p < *q) *p= *q; k++; } } //backward r= buf + width * (height - 2); dd-= 2.0 * di; k= (height - 1) % (n + 1); for (j= 1; j < height; j++, dd-= di, r-= width) { if (dd >= 0.5) { dd-= 1.0; i= 1; p= r + 1; q= r + width; } else if (dd < -0.5) { dd+= 1.0; i= 1; p= r; q= r + width + 1; } else { i= 0; p= r; q= r + width; } if (k < 1) k= n; else { for (; i < width; i++, p++, q++) if (*p < *q) *p= *q; k--; } } //join forward double dd1, dd2; int np= n - n / 2; int nr= n - np; dd1= 0.0; dd= np * di; dd2= n * di; for (j= n; j < height; j++, dd1+= di, dd+= di, dd2+= di) { //TODO optimize ptrdiff_t n0; if (di < 0) { n0= ptrdiff_t(floor(dd2+0.5)); q= src + (j - nr) * width + (ptrdiff_t(floor(dd+0.5)) - n0); i= ptrdiff_t(floor(dd1+0.5)) - n0; r= buf + (j - n) * width + i; p= src + j * width; } else { n0= ptrdiff_t(floor(dd1+0.5)); q= src + (j - nr) * width + (ptrdiff_t(floor(dd+0.5)) - n0); i= ptrdiff_t(floor(dd2+0.5)) - n0; p= src + j * width + i; r= buf + (j - n) * width; } for (; i < width; i++, p++, q++, r++) if (*p < *r) *q= *r; else *q= *p; } } break; } } template void erode2D_lin (F* src, ptrdiff_t width, ptrdiff_t height, int n, int rot, double di, F *buf) { ptrdiff_t i, j, k; ptrdiff_t size= width * height; F *p, *q, *r; double dd; if (n < 1) return; memcpy(buf, src, size * sizeof(F)); switch(rot) { case rot0: { //forward for (j= 1, r= src + 1, dd= di, k= 1; j < width; j++, dd+= di, r++) { if (dd >= 0.5) { dd-= 1.0; i= 1; p= r + width; q= r - 1; } else if (dd < -0.5) { dd+= 1.0; i= 1; p= r; q= r - 1 + width; } else { i= 0; p= r; q= r - 1; } if (k > n) k= 1; else { for (; i < height; i++, p+= width, q+= width) if (*p > *q) *p= *q; k++; } } //backward r= buf + width - 2; dd-= 2.0 * di; k= (width - 1) % (n + 1); for (j= 1; j < width; j++, dd-= di, r--) { if (dd >= 0.5) { dd-= 1.0; i= 1; p= r + width; q= r + 1; } else if (dd < -0.5) { dd+= 1.0; i= 1; p= r; q= r + 1 + width; } else { i= 0; p= r; q= r + 1; } if (k < 1) k= n; else { for (; i < height; i++, p+= width, q+= width) if (*p > *q) *p= *q; k--; } } //join forward double dd1, dd2; int np= n - n / 2; int nr= n - np; dd1= 0.0; dd= np * di; dd2= n * di; for (j= n; j < width; j++, dd1+= di, dd+= di, dd2+= di) { //TODO optimize ptrdiff_t n0; if (di < 0) { n0= ptrdiff_t(floor(dd2+0.5)); q= src + j - nr + width * (ptrdiff_t(floor(dd+0.5)) - n0); i= ptrdiff_t(floor(dd1+0.5)) - n0; r= buf + j - n + i * width; p= src + j; } else { n0= ptrdiff_t(floor(dd1+0.5)); q= src + j - nr + width * (ptrdiff_t(floor(dd+0.5)) - n0); i= ptrdiff_t(floor(dd2+0.5)) - n0; p= src + j + i * width; r= buf + j - n; } for (; i < height; i++, p+= width, q+= width, r+= width) if (*p > *r) *q= *r; else *q= *p; } } break; case rot90: { //forward for (j= 1, r= src + width, dd= di, k= 1; j < height; j++, dd+= di, r+= width) { if (dd >= 0.5) { dd-= 1.0; i= 1; p= r + 1; q= r - width; } else if (dd < -0.5) { dd+= 1.0; i= 1; p= r; q= r - width + 1; } else { i= 0; p= r; q= r - width; } if (k > n) k= 1; else { for (; i < width; i++, p++, q++) if (*p > *q) *p= *q; k++; } } //backward r= buf + width * (height - 2); dd-= 2.0 * di; k= (height - 1) % (n + 1); for (j= 1; j < height; j++, dd-= di, r-= width) { if (dd >= 0.5) { dd-= 1.0; i= 1; p= r + 1; q= r + width; } else if (dd < -0.5) { dd+= 1.0; i= 1; p= r; q= r + width + 1; } else { i= 0; p= r; q= r + width; } if (k < 1) k= n; else { for (; i < width; i++, p++, q++) if (*p > *q) *p= *q; k--; } } //join forward double dd1, dd2; int np= n - n / 2; int nr= n - np; dd1= 0.0; dd= np * di; dd2= n * di; for (j= n; j < height; j++, dd1+= di, dd+= di, dd2+= di) { //TODO optimize ptrdiff_t n0; if (di < 0) { n0= ptrdiff_t(floor(dd2+0.5)); q= src + (j - nr) * width + (ptrdiff_t(floor(dd+0.5)) - n0); i= ptrdiff_t(floor(dd1+0.5)) - n0; r= buf + (j - n) * width + i; p= src + j * width; } else { n0= ptrdiff_t(floor(dd1+0.5)); q= src + (j - nr) * width + (ptrdiff_t(floor(dd+0.5)) - n0); i= ptrdiff_t(floor(dd2+0.5)) - n0; p= src + j * width + i; r= buf + (j - n) * width; } for (; i < width; i++, p++, q++, r++) if (*p > *r) *q= *r; else *q= *p; } } break; } } template void Dilate2DLin(Image& I, int num, double angle) { int i; F *q, *pdat; if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic = DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step = I.dims[0] * I.dims[1]; q= I.data; pdat= new F[step]; int n1, n2, rot; double di; getlinpar2d(num, angle, n1, n2, rot, di); for (i= 0; i < numslic; i++) { dilate2D_lin (q, I.dims[0], I.dims[1], n1, rot, di, pdat); q+= step; } delete [] pdat; } template void Erode2DLin(Image& I, int num, double angle) { ptrdiff_t i; F *q, *pdat; if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; q= I.data; pdat= new F[step]; int n1, n2, rot; double di; getlinpar2d(num, angle, n1, n2, rot, di); for (i= 0; i < numslic; i++) { erode2D_lin (q, I.dims[0], I.dims[1], n1, rot, di, pdat); q+= step; } delete [] pdat; } template void Close2DLin(Image& I, int num, double angle) { ptrdiff_t i; F *q, *pdat; if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; q= I.data; pdat= new F[step]; int n1, n2, rot; double di; getlinpar2d(num, angle, n1, n2, rot, di); for (i= 0; i < numslic; i++) { dilate2D_lin (q, I.dims[0], I.dims[1], n1, rot, di, pdat); erode2D_lin (q, I.dims[0], I.dims[1], n1, rot, di, pdat); q+= step; } delete [] pdat; } template void Open2DLin(Image& I, int num, double angle) { ptrdiff_t i; F *q, *pdat; if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; q= I.data; pdat= new F[step]; int n1, n2, rot; double di; getlinpar2d(num, angle, n1, n2, rot, di); for (i= 0; i < numslic; i++) { erode2D_lin (q, I.dims[0], I.dims[1], n1, rot, di, pdat); dilate2D_lin (q, I.dims[0], I.dims[1], n1, rot, di, pdat); q+= step; } delete [] pdat; } template void Dilate2DLinN (Image& I, int num, int steps, double angle0= 0.0) { Img pImg1(I); Img pImg2(I); double angle= angle0; double dangle= M_PI / steps; pImg2.SetData(IL_GU_SET,(F)std::numeric_limits::max()); int k; for(k= 0; k < steps; k++, angle+= dangle) { pImg1.SetData(I.data); Dilate2DLin(pImg1, num, angle); pImg2.SetData(IL_GB_MIN,pImg1.data); } I.SetData(pImg2.data); } template void Erode2DLinN (Image& I, int num, int steps, double angle0= 0.0) { Img pImg1(I); Img pImg2(I); double angle= angle0; double dangle= M_PI / steps; pImg2.SetData(); int k; for(k= 0; k < steps; k++, angle+= dangle) { pImg1.SetData(I.data); Erode2DLin(pImg1, num, angle); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); } template void Close2DLinN (Image& I, int num, int steps, double angle0= 0.0) { Img pImg1(I); Img pImg2(I); double angle= angle0; double dangle= M_PI / steps; pImg2.SetData(); int k; for(k= 0; k < steps; k++, angle+= dangle) { pImg1.SetData(I.data); Close2DLin(pImg1, num, angle); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); } template void Open2DLinN (Image& I, int num, int steps, double angle0= 0.0) { Img pImg1(I); Img pImg2(I); double angle= angle0; double dangle= M_PI / steps; pImg2.SetData(); int k; for(k= 0; k < steps; k++, angle+= dangle) { pImg1.SetData(I.data); Open2DLin(pImg1, num, angle); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); } template void movavg2D_lin (F* src, ptrdiff_t width, ptrdiff_t height, int n, int rot, double di, F *buf) { ptrdiff_t i, j, k; ptrdiff_t size= width * height; F *p, *q, *r; double dd; if (n < 1) return; memcpy(buf, src, size * sizeof(F)); switch(rot) { case rot0: { //forward for (j= 1, r= src + 1, dd= di, k= 1; j < width; j++, dd+= di, r++) { if (dd >= 0.5) { dd-= 1.0; i= 1; p= r + width; q= r - 1; } else if (dd < -0.5) { dd+= 1.0; i= 1; p= r; q= r - 1 + width; } else { i= 0; p= r; q= r - 1; } if (k > n) k= 1; else { for (; i < height; i++, p+= width, q+= width) *p+= *q; k++; } } //backward r= buf + width - 2; dd-= 2.0 * di; k= (width - 1) % (n + 1); for (j= 1; j < width; j++, dd-= di, r--) { if (dd >= 0.5) { dd-= 1.0; i= 1; p= r + width; q= r + 1; } else if (dd < -0.5) { dd+= 1.0; i= 1; p= r; q= r + 1 + width; } else { i= 0; p= r; q= r + 1; } if (k < 1) k= n; else { for (; i < height; i++, p+= width, q+= width) *p+= *q; k--; } } //join forward double dd1, dd2; int np= n - n / 2; int nr= n - np; dd1= 0.0; dd= np * di; dd2= n * di; for (j= n, k= 1; j < width; j++, dd1+= di, dd+= di, dd2+= di) { //TODO optimize ptrdiff_t n0; if (di < 0) { n0= ptrdiff_t(floor(dd2+0.5)); q= src + j - nr + width * (ptrdiff_t(floor(dd+0.5)) - n0); i= ptrdiff_t(floor(dd1+0.5)) - n0; r= buf + j - n + i * width; p= src + j; } else { n0= ptrdiff_t(floor(dd1+0.5)); q= src + j - nr + width * (ptrdiff_t(floor(dd+0.5)) - n0); i= ptrdiff_t(floor(dd2+0.5)) - n0; p= src + j + i * width; r= buf + j - n; } if (k == 1) for (; i < height; i++, p+= width, q+= width, r+= width) *q= *p; else for (; i < height; i++, p+= width, q+= width, r+= width) *q= *r + *p; if (k > n) k= 1; else k++; } } break; case rot90: { //forward for (j= 1, r= src + width, dd= di, k= 1; j < height; j++, dd+= di, r+= width) { if (dd >= 0.5) { dd-= 1.0; i= 1; p= r + 1; q= r - width; } else if (dd < -0.5) { dd+= 1.0; i= 1; p= r; q= r - width + 1; } else { i= 0; p= r; q= r - width; } if (k > n) k= 1; else { for (; i < width; i++, p++, q++) *p+= *q; k++; } } //backward r= buf + width * (height - 2); dd-= 2.0 * di; k= (height - 1) % (n + 1); for (j= 1; j < height; j++, dd-= di, r-= width) { if (dd >= 0.5) { dd-= 1.0; i= 1; p= r + 1; q= r + width; } else if (dd < -0.5) { dd+= 1.0; i= 1; p= r; q= r + width + 1; } else { i= 0; p= r; q= r + width; } if (k < 1) k= n; else { for (; i < width; i++, p++, q++) *p+= *q; k--; } } //join forward double dd1, dd2; int np= n - n / 2; int nr= n - np; dd1= 0.0; dd= np * di; dd2= n * di; for (j= n, k= 1; j < height; j++, dd1+= di, dd+= di, dd2+= di) { //TODO optimize ptrdiff_t n0; if (di < 0) { n0= ptrdiff_t(floor(dd2+0.5)); q= src + (j - nr) * width + (ptrdiff_t(floor(dd+0.5)) - n0); i= ptrdiff_t(floor(dd1+0.5)) - n0; r= buf + (j - n) * width + i; p= src + j * width; } else { n0= ptrdiff_t(floor(dd1+0.5)); q= src + (j - nr) * width + (ptrdiff_t(floor(dd+0.5)) - n0); i= ptrdiff_t(floor(dd2+0.5)) - n0; p= src + j * width + i; r= buf + (j - n) * width; } if (k == 1) for (; i < width; i++, p++, q++, r++) *q= *p; else for (; i < width; i++, p++, q++, r++) *q= *r + *p; if (k > n) k= 1; else k++; } } break; } } template void MovAvg2DLin(Image& I, int num, double angle) { ptrdiff_t i, j; F *q; if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; q= I.data; Image pImg(2,I.dims); F *pdat= new F[step]; int n1, n2, rot; double di; getlinpar2d(num, angle, n1, n2, rot, di); for (i= 0; i < numslic; i++) { movavg2D_lin (q, I.dims[0], I.dims[1], n1, rot, di, pdat); pImg.data= q; pImg.SetData(IL_GU_DIV, n1); q+= step; } delete [] pdat; } template void MovAvg2DLin(Image& I, int num, double angle) { ptrdiff_t i, j; F *q; if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; q= I.data; Img pImg(2,I.dims); G *pdat= new G[step]; int n1, n2, rot; double di; getlinpar2d(num, angle, n1, n2, rot, di); for (i= 0; i < numslic; i++) { pImg.SetData(q); movavg2D_lin (pImg.data, I.dims[0], I.dims[1], n1, rot, di, pdat); pImg.SetData(IL_GU_DIV, n1); pImg.GetData(q); q+= step; } delete [] pdat; } #undef rot0 #undef rot90 template void Dilate2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0= 0.0) { Img pImg1(I); Img pImg2(I); double angle= angle0; double dangle= M_PI / steps; pImg2.SetData(IL_GU_SET,(F)std::numeric_limits::max()); int k; for(k= 0; k < steps; k++, angle+= dangle) { pImg1.SetData(I.data); MovAvg2DLin(pImg1, numma, angle); Dilate2DLin(pImg1, num, angle); pImg2.SetData(IL_GB_MIN,pImg1.data); } I.SetData(pImg2.data); } template void Dilate2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0= 0.0) { Img pImg1(I); Img pImg2(I); double angle= angle0; double dangle= M_PI / steps; pImg2.SetData(IL_GU_SET,(F)std::numeric_limits::max()); int k; for(k= 0; k < steps; k++, angle+= dangle) { pImg1.SetData(I.data); MovAvg2DLin(pImg1, numma, angle); Dilate2DLin(pImg1, num, angle); pImg2.SetData(IL_GB_MIN,pImg1.data); } I.SetData(pImg2.data); } template void Erode2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0= 0.0) { Img pImg1(I); Img pImg2(I); double angle= angle0; double dangle= M_PI / steps; pImg2.SetData(); int k; for(k= 0; k < steps; k++, angle+= dangle) { pImg1.SetData(I.data); MovAvg2DLin(pImg1, numma, angle); Erode2DLin(pImg1, num, angle); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); } template void Erode2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0= 0.0) { Img pImg1(I); Img pImg2(I); double angle= angle0; double dangle= M_PI / steps; pImg2.SetData(); int k; for(k= 0; k < steps; k++, angle+= dangle) { pImg1.SetData(I.data); MovAvg2DLin(pImg1, numma, angle); Erode2DLin(pImg1, num, angle); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); } template void Close2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0= 0.0) { Img pImg1(I); Img pImg2(I); double angle= angle0; double dangle= M_PI / steps; // pImg2.SetData(IL_GU_SET,(F)std::numeric_limits::max()); pImg2.SetData(); int k; for(k= 0; k < steps; k++, angle+= dangle) { pImg1.SetData(I.data); MovAvg2DLin(pImg1, numma, angle); Close2DLin(pImg1, num, angle); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); } template void Close2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0= 0.0) { Img pImg1(I); Img pImg2(I); double angle= angle0; double dangle= M_PI / steps; // pImg2.SetData(IL_GU_SET,(F)std::numeric_limits::max()); pImg2.SetData(); int k; for(k= 0; k < steps; k++, angle+= dangle) { pImg1.SetData(I.data); MovAvg2DLin(pImg1, numma, angle); Close2DLin(pImg1, num, angle); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); } template void Open2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0= 0.0) { Img pImg1(I); Img pImg2(I); double angle= angle0; double dangle= M_PI / steps; pImg2.SetData(); int k; for(k= 0; k < steps; k++, angle+= dangle) { pImg1.SetData(I.data); MovAvg2DLin(pImg1, numma, angle); Open2DLin(pImg1, num, angle); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); } template void Open2DLinNSmooth (Image& I, int num, int steps, int numma, double angle0= 0.0) { Img pImg1(I); Img pImg2(I); double angle= angle0; double dangle= M_PI / steps; pImg2.SetData(); int k; for(k= 0; k < steps; k++, angle+= dangle) { pImg1.SetData(I.data); MovAvg2DLin(pImg1, numma, angle); Open2DLin(pImg1, num, angle); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); } #define x_dir 0 #define y_dir 1 #define z_dir 2 //lattitude from -M_PI/2 to M_PI/2, longitude from 0 to 2*M_PI template void getlinpar3d(double xcal, double ycal, double zcal, int num, double lattitude, double longitude, int& n1, int& n2, int& n3, int& dir, double& ddx, double& ddy) { double iz[3]= {cos(longitude) * cos(lattitude) / xcal, sin(longitude) * cos(lattitude) / ycal, sin(lattitude) / zcal}; if (fabs(iz[0]) > fabs(iz[1])) if (fabs(iz[0]) > fabs(iz[2])) dir= x_dir; else dir= z_dir; else if (fabs(iz[1]) > fabs(iz[2])) dir= y_dir; else dir= z_dir; switch (dir) { case x_dir: ddx= iz[1] / iz[0]; ddy= iz[2] / iz[0]; n1= (int)floor(num / sqrt(xcal * xcal + ddx * ycal * ddx * ycal + ddy * zcal * ddy * zcal)+0.5); break; case y_dir: ddx= iz[0] / iz[1]; ddy= iz[2] / iz[1]; n1= (int)floor(num / sqrt(ycal * ycal + ddx * xcal * ddx * xcal + ddy * zcal * ddy * zcal)+0.5); break; case z_dir: ddx= iz[0] / iz[2]; ddy= iz[1] / iz[2]; n1= (int)floor(num / sqrt(zcal * zcal + ddx * xcal * ddx * xcal + ddy * ycal * ddy * ycal)+0.5); break; } n2= (int)floor(fabs(ddx) * n1 + 0.5); n3= (int)floor(fabs(ddy) * n1 + 0.5); } template void dilate3D_lin (F* src, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, int n, int dir, double ddx, double ddy, F* buf) { ptrdiff_t i, j, k, i0, l; ptrdiff_t Ssize= width * height; ptrdiff_t size= Ssize * depth; F *p, *q, *r, *t, *u, *v; double dx, dy; if (n < 1) return; memcpy(buf, src, size * sizeof(F)); switch(dir) { case x_dir: { //forward for (j= 1, r= src + 1, dx= ddx, dy= ddy, k= 1; j < width; j++, dx+= ddx, dy+= ddy, r++) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp+= width; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq+= width; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= Ssize; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= Ssize; } else l= 0; if (k > n) k= 1; else { for (t= r + dp, u= r - 1 + dq; l < depth; l++, t+= Ssize, u+= Ssize) for (i= i0, p= t, q= u; i < height; i++, p+= width, q+= width) if (*p < *q) *p= *q; k++; } } //backward r= buf + width - 2; dx-= 2 * ddx; dy-= 2 * ddy; k= (width - 1) % (n + 1); for (j= 1; j < width; j++, dx-= ddx, dy-= ddy, r--) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp+= width; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq+= width; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= Ssize; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= Ssize; } else l= 0; if (k < 1) k= n; else { for (t= r + dp, u= r + 1 + dq; l < depth; l++, t+= Ssize, u+= Ssize) for (i= i0, p= t, q= u; i < height; i++, p+= width, q+= width) if (*p < *q) *p= *q; k--; } } //join forward double dx1, dx2, dy1, dy2; int np= n - n / 2; int nr= n - np; dx1= 0.0; dx= np * ddx; dx2= n * ddx; dy1= 0.0; dy= np * ddy; dy2= n * ddy; for (j= n; j < width; j++, dx1+= ddx, dx+= ddx, dx2+= ddx, dy1+= ddy, dy+= ddy, dy2+= ddy) { //TODO optimize ptrdiff_t n0; ptrdiff_t dp= 0; ptrdiff_t dq= 0; ptrdiff_t dr= 0; if (ddx < 0) { n0= ptrdiff_t(floor(dx2+0.5)); dq+= width * (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx1+0.5)) - n0; dr+= i0 * width; } else { n0= ptrdiff_t(floor(dx1+0.5)); dq+= width * (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx2+0.5)) - n0; dp+= i0 * width; } if (ddy < 0) { n0= ptrdiff_t(floor(dy2+0.5)); dq+= Ssize * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy1+0.5)) - n0; dr+= l * Ssize; } else { n0= ptrdiff_t(floor(dy1+0.5)); dq+= Ssize * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy2+0.5)) - n0; dp+= l * Ssize; } for (t= buf + j - n + dr, u= src + j - nr + dq, v= src + j + dp; l < depth; l++, t+= Ssize, u+= Ssize, v+= Ssize) for (i= i0, r= t, q= u, p= v; i < height; i++, p+= width, q+= width, r+= width) if (*p < *r) *q= *r; else *q= *p; } } break; case y_dir:{ //forward for (j= 1, r= src + width, dx= ddx, dy= ddy, k= 1; j < height; j++, dx+= ddx, dy+= ddy, r+= width) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp++; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq++; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= Ssize; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= Ssize; } else l= 0; if (k > n) k= 1; else { for (t= r + dp, u= r - width + dq; l < depth; l++, t+= Ssize, u+= Ssize) for (i= i0, p= t, q= u; i < width; i++, p++, q++) if (*p < *q) *p= *q; k++; } } //backward r= buf + width * (height - 2); dx-= 2 * ddx; dy-= 2 * ddy; k= (height - 1) % (n + 1); for (j= 1; j < height; j++, dx-= ddx, dy-= ddy, r-= width) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp++; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq++; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= Ssize; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= Ssize; } else l= 0; if (k < 1) k= n; else { for (t= r + dp, u= r + width + dq; l < depth; l++, t+= Ssize, u+= Ssize) for (i= i0, p= t, q= u; i < width; i++, p++, q++) if (*p < *q) *p= *q; k--; } } //join forward double dx1, dx2, dy1, dy2; int np= n - n / 2; int nr= n - np; dx1= 0.0; dx= np * ddx; dx2= n * ddx; dy1= 0.0; dy= np * ddy; dy2= n * ddy; for (j= n; j < height; j++, dx1+= ddx, dx+= ddx, dx2+= ddx, dy1+= ddy, dy+= ddy, dy2+= ddy) { //TODO optimize ptrdiff_t n0; ptrdiff_t dp= 0; ptrdiff_t dq= 0; ptrdiff_t dr= 0; if (ddx < 0) { n0= ptrdiff_t(floor(dx2+0.5)); dq+= (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx1+0.5)) - n0; dr+= i0; } else { n0= ptrdiff_t(floor(dx1+0.5)); dq+= (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx2+0.5)) - n0; dp+= i0; } if (ddy < 0) { n0= ptrdiff_t(floor(dy2+0.5)); dq+= Ssize * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy1+0.5)) - n0; dr+= l * Ssize; } else { n0= ptrdiff_t(floor(dy1+0.5)); dq+= Ssize * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy2+0.5)) - n0; dp+= l * Ssize; } for (t= buf + width * (j - n) + dr, u= src + width * (j - nr) + dq, v= src + width * j + dp; l < depth; l++, t+= Ssize, u+= Ssize, v+= Ssize) for (i= i0, r= t, q= u, p= v; i < width; i++, p++, q++, r++) if (*p < *r) *q= *r; else *q= *p; } } break; case z_dir:{ //forward for (j= 1, r= src + Ssize, dx= ddx, dy= ddy, k= 1; j < depth; j++, dx+= ddx, dy+= ddy, r+= Ssize) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp++; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq++; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= width; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= width; } else l= 0; if (k > n) k= 1; else { for (t= r + dp, u= r - Ssize + dq; l < height; l++, t+= width, u+= width) for (i= i0, p= t, q= u; i < width; i++, p++, q++) if (*p < *q) *p= *q; k++; } } //backward r= buf + Ssize * (depth - 2); dx-= 2 * ddx; dy-= 2 * ddy; k= (depth - 1) % (n + 1); for (j= 1; j < depth; j++, dx-= ddx, dy-= ddy, r-= Ssize) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp++; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq++; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= width; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= width; } else l= 0; if (k < 1) k= n; else { for (t= r + dp, u= r + Ssize + dq; l < height; l++, t+= width, u+= width) for (i= i0, p= t, q= u; i < width; i++, p++, q++) if (*p < *q) *p= *q; k--; } } //join forward double dx1, dx2, dy1, dy2; int np= n - n / 2; int nr= n - np; dx1= 0.0; dx= np * ddx; dx2= n * ddx; dy1= 0.0; dy= np * ddy; dy2= n * ddy; for (j= n; j < depth; j++, dx1+= ddx, dx+= ddx, dx2+= ddx, dy1+= ddy, dy+= ddy, dy2+= ddy) { //TODO optimize ptrdiff_t n0; ptrdiff_t dp= 0; ptrdiff_t dq= 0; ptrdiff_t dr= 0; if (ddx < 0) { n0= ptrdiff_t(floor(dx2+0.5)); dq+= (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx1+0.5)) - n0; dr+= i0; } else { n0= ptrdiff_t(floor(dx1+0.5)); dq+= (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx2+0.5)) - n0; dp+= i0; } if (ddy < 0) { n0= ptrdiff_t(floor(dy2+0.5)); dq+= width * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy1+0.5)) - n0; dr+= l * width; } else { n0= ptrdiff_t(floor(dy1+0.5)); dq+= width * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy2+0.5)) - n0; dp+= l * width; } for (t= buf + Ssize * (j - n) + dr, u= src + Ssize * (j - nr) + dq, v= src + Ssize * j + dp; l < height; l++, t+= width, u+= width, v+= width) for (i= i0, r= t, q= u, p= v; i < width; i++, p++, q++, r++) if (*p < *r) *q= *r; else *q= *p; } } break; } } template void erode3D_lin (F* src, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, int n, int dir, double ddx, double ddy, F* buf) { ptrdiff_t i, j, k, i0, l; ptrdiff_t Ssize= width * height; ptrdiff_t size= Ssize * depth; F *p, *q, *r, *t, *u, *v; double dx, dy; if (n < 1) return; memcpy(buf, src, size * sizeof(F)); switch(dir) { case x_dir: { //forward for (j= 1, r= src + 1, dx= ddx, dy= ddy, k= 1; j < width; j++, dx+= ddx, dy+= ddy, r++) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp+= width; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq+= width; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= Ssize; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= Ssize; } else l= 0; if (k > n) k= 1; else { for (t= r + dp, u= r - 1 + dq; l < depth; l++, t+= Ssize, u+= Ssize) for (i= i0, p= t, q= u; i < height; i++, p+= width, q+= width) if (*p > *q) *p= *q; k++; } } //backward r= buf + width - 2; dx-= 2 * ddx; dy-= 2 * ddy; k= (width - 1) % (n + 1); for (j= 1; j < width; j++, dx-= ddx, dy-= ddy, r--) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp+= width; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq+= width; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= Ssize; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= Ssize; } else l= 0; if (k < 1) k= n; else { for (t= r + dp, u= r + 1 + dq; l < depth; l++, t+= Ssize, u+= Ssize) for (i= i0, p= t, q= u; i < height; i++, p+= width, q+= width) if (*p > *q) *p= *q; k--; } } //join forward double dx1, dx2, dy1, dy2; int nr= n - n / 2; int np= n - nr; dx1= 0.0; dx= np * ddx; dx2= n * ddx; dy1= 0.0; dy= np * ddy; dy2= n * ddy; for (j= n; j < width; j++, dx1+= ddx, dx+= ddx, dx2+= ddx, dy1+= ddy, dy+= ddy, dy2+= ddy) { //TODO optimize ptrdiff_t n0; ptrdiff_t dp= 0; ptrdiff_t dq= 0; ptrdiff_t dr= 0; if (ddx < 0) { n0= ptrdiff_t(floor(dx2+0.5)); dq+= width * (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx1+0.5)) - n0; dr+= i0 * width; } else { n0= ptrdiff_t(floor(dx1+0.5)); dq+= width * (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx2+0.5)) - n0; dp+= i0 * width; } if (ddy < 0) { n0= ptrdiff_t(floor(dy2+0.5)); dq+= Ssize * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy1+0.5)) - n0; dr+= l * Ssize; } else { n0= ptrdiff_t(floor(dy1+0.5)); dq+= Ssize * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy2+0.5)) - n0; dp+= l * Ssize; } for (t= buf + j - n + dr, u= src + j - nr + dq, v= src + j + dp; l < depth; l++, t+= Ssize, u+= Ssize, v+= Ssize) for (i= i0, r= t, q= u, p= v; i < height; i++, p+= width, q+= width, r+= width) if (*p > *r) *q= *r; else *q= *p; } } break; case y_dir:{ //forward for (j= 1, r= src + width, dx= ddx, dy= ddy, k= 1; j < height; j++, dx+= ddx, dy+= ddy, r+= width) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp++; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq++; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= Ssize; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= Ssize; } else l= 0; if (k > n) k= 1; else { for (t= r + dp, u= r - width + dq; l < depth; l++, t+= Ssize, u+= Ssize) for (i= i0, p= t, q= u; i < width; i++, p++, q++) if (*p > *q) *p= *q; k++; } } //backward r= buf + width * (height - 2); dx-= 2 * ddx; dy-= 2 * ddy; k= (height - 1) % (n + 1); for (j= 1; j < height; j++, dx-= ddx, dy-= ddy, r-= width) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp++; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq++; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= Ssize; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= Ssize; } else l= 0; if (k < 1) k= n; else { for (t= r + dp, u= r + width + dq; l < depth; l++, t+= Ssize, u+= Ssize) for (i= i0, p= t, q= u; i < width; i++, p++, q++) if (*p > *q) *p= *q; k--; } } //join forward double dx1, dx2, dy1, dy2; int nr= n - n / 2; int np= n - nr; dx1= 0.0; dx= np * ddx; dx2= n * ddx; dy1= 0.0; dy= np * ddy; dy2= n * ddy; for (j= n; j < height; j++, dx1+= ddx, dx+= ddx, dx2+= ddx, dy1+= ddy, dy+= ddy, dy2+= ddy) { //TODO optimize ptrdiff_t n0; ptrdiff_t dp= 0; ptrdiff_t dq= 0; ptrdiff_t dr= 0; if (ddx < 0) { n0= ptrdiff_t(floor(dx2+0.5)); dq+= (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx1+0.5)) - n0; dr+= i0; } else { n0= ptrdiff_t(floor(dx1+0.5)); dq+= (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx2+0.5)) - n0; dp+= i0; } if (ddy < 0) { n0= ptrdiff_t(floor(dy2+0.5)); dq+= Ssize * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy1+0.5)) - n0; dr+= l * Ssize; } else { n0= ptrdiff_t(floor(dy1+0.5)); dq+= Ssize * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy2+0.5)) - n0; dp+= l * Ssize; } for (t= buf + width * (j - n) + dr, u= src + width * (j - nr) + dq, v= src + width * j + dp; l < depth; l++, t+= Ssize, u+= Ssize, v+= Ssize) for (i= i0, r= t, q= u, p= v; i < width; i++, p++, q++, r++) if (*p > *r) *q= *r; else *q= *p; } } break; case z_dir:{ //forward for (j= 1, r= src + Ssize, dx= ddx, dy= ddy, k= 1; j < depth; j++, dx+= ddx, dy+= ddy, r+= Ssize) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp++; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq++; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= width; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= width; } else l= 0; if (k > n) k= 1; else { for (t= r + dp, u= r - Ssize + dq; l < height; l++, t+= width, u+= width) for (i= i0, p= t, q= u; i < width; i++, p++, q++) if (*p > *q) *p= *q; k++; } } //backward r= buf + Ssize * (depth - 2); dx-= 2 * ddx; dy-= 2 * ddy; k= (depth - 1) % (n + 1); for (j= 1; j < depth; j++, dx-= ddx, dy-= ddy, r-= Ssize) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp++; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq++; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= width; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= width; } else l= 0; if (k < 1) k= n; else { for (t= r + dp, u= r + Ssize + dq; l < height; l++, t+= width, u+= width) for (i= i0, p= t, q= u; i < width; i++, p++, q++) if (*p > *q) *p= *q; k--; } } //join forward double dx1, dx2, dy1, dy2; int nr= n - n / 2; int np= n - nr; dx1= 0.0; dx= np * ddx; dx2= n * ddx; dy1= 0.0; dy= np * ddy; dy2= n * ddy; for (j= n; j < depth; j++, dx1+= ddx, dx+= ddx, dx2+= ddx, dy1+= ddy, dy+= ddy, dy2+= ddy) { //TODO optimize ptrdiff_t n0; ptrdiff_t dp= 0; ptrdiff_t dq= 0; ptrdiff_t dr= 0; if (ddx < 0) { n0= ptrdiff_t(floor(dx2+0.5)); dq+= (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx1+0.5)) - n0; dr+= i0; } else { n0= ptrdiff_t(floor(dx1+0.5)); dq+= (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx2+0.5)) - n0; dp+= i0; } if (ddy < 0) { n0= ptrdiff_t(floor(dy2+0.5)); dq+= width * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy1+0.5)) - n0; dr+= l * width; } else { n0= ptrdiff_t(floor(dy1+0.5)); dq+= width * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy2+0.5)) - n0; dp+= l * width; } for (t= buf + Ssize * (j - n) + dr, u= src + Ssize * (j - nr) + dq, v= src + Ssize * j + dp; l < height; l++, t+= width, u+= width, v+= width) for (i= i0, r= t, q= u, p= v; i < width; i++, p++, q++, r++) if (*p > *r) *q= *r; else *q= *p; } } break; } } template void Dilate3DLin (Image& I, int num, double lattitude, double longitude) { int i; F *q, *pdat; if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; int numslic= DimsProd(I.nDim - 3, I.dims + 3); int step= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; Image pImg(3,I.dims); pdat= new F[step]; int n1, n2, n3, rot; double di1, di2; getlinpar3d(I.Dx(0), I.Dx(1), I.Dx(2), num, lattitude, longitude, n1, n2, n3, rot, di1, di2); for (i= 0; i < numslic; i++) { dilate3D_lin (q, I.dims[0], I.dims[1], I.dims[2], n1, rot, di1, di2, pdat); q+= step; } delete [] pdat; } template void Erode3DLin (Image& I, int num, double lattitude, double longitude) { int i; F *q, *pdat; if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; int numslic= DimsProd(I.nDim - 3, I.dims + 3); int step= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; Image pImg(3,I.dims); pdat= new F[step]; int n1, n2, n3, rot; double di1, di2; getlinpar3d(I.Dx(0), I.Dx(1), I.Dx(2), num, lattitude, longitude, n1, n2, n3, rot, di1, di2); for (i= 0; i < numslic; i++) { erode3D_lin (q, I.dims[0], I.dims[1], I.dims[2], n1, rot, di1, di2, pdat); q+= step; } delete [] pdat; } //template void Close3DLin (Image& I, int num, double lattitude, double longitude) { // Dilate3DLin(I, num, lattitude, longitude); // Erode3DLin(I, num, lattitude, longitude); //} // //template void Open3DLin (Image& I, int num, double lattitude, double longitude) { // Erode3DLin(I, num, lattitude, longitude); // Dilate3DLin(I, num, lattitude, longitude); //} template void Close3DLin (Image& I, int num, double lattitude, double longitude) { int i; F *q, *pdat; if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; int numslic= DimsProd(I.nDim - 3, I.dims + 3); int step= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; Image pImg(3,I.dims); pdat= new F[step]; int n1, n2, n3, rot; double di1, di2; getlinpar3d(I.Dx(0), I.Dx(1), I.Dx(2), num, lattitude, longitude, n1, n2, n3, rot, di1, di2); for (i= 0; i < numslic; i++) { dilate3D_lin (q, I.dims[0], I.dims[1], I.dims[2], n1, rot, di1, di2, pdat); erode3D_lin (q, I.dims[0], I.dims[1], I.dims[2], n1, rot, di1, di2, pdat); q+= step; } delete [] pdat; } template void Open3DLin (Image& I, int num, double lattitude, double longitude) { int i; F *q, *pdat; if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; int numslic= DimsProd(I.nDim - 3, I.dims + 3); int step= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; Image pImg(3,I.dims); pdat= new F[step]; int n1, n2, n3, rot; double di1, di2; getlinpar3d(I.Dx(0), I.Dx(1), I.Dx(2), num, lattitude, longitude, n1, n2, n3, rot, di1, di2); for (i= 0; i < numslic; i++) { erode3D_lin (q, I.dims[0], I.dims[1], I.dims[2], n1, rot, di1, di2, pdat); dilate3D_lin (q, I.dims[0], I.dims[1], I.dims[2], n1, rot, di1, di2, pdat); q+= step; } delete [] pdat; } template double** gen_syst_3d(int steps) { double **x; if (steps == 0) { x= new double*[1]; x[0]= new double[3]; x[0][0]= 0.0; x[0][1]= 1.0; x[0][2]= 0.0; return x; } else if (GenIcosaSyst(steps, x)) return x; else return 0; } template void Dilate3DLinN (Image& I, int num, int steps, double lattitude0= 0.0, double longitude0= 0.0) { Img pImg1(I); Img pImg2(I); int num_nodes= GetIcosaNum(steps); double **x= gen_syst_3d(steps); if (!x) return; pImg2.SetData(IL_GU_SET,(F)std::numeric_limits::max()); int k; for(k= 0; k < num_nodes; k++) { double x1[3], x2[3]; x1[0]= x[k][0]; x1[1]= cos(lattitude0) * x[k][1] - sin(lattitude0) * x[k][2]; x1[2]= sin(lattitude0) * x[k][1] + cos(lattitude0) * x[k][2]; x2[0]= cos(longitude0) * x1[0] - sin(longitude0) * x1[1]; x2[1]= sin(longitude0) * x1[0] + cos(longitude0) * x1[1]; x2[2]= x1[2]; double lattitude= asin(x2[2]); double longitude= atan2(x2[1],x2[0]); pImg1.SetData(I.data); Dilate3DLin(pImg1,num,lattitude,longitude); pImg2.SetData(IL_GB_MIN,pImg1.data); } I.SetData(pImg2.data); delete[] x[0]; delete[] x; } template void Erode3DLinN (Image& I, int num, int steps, double lattitude0= 0.0, double longitude0= 0.0) { Img pImg1(I); Img pImg2(I); int num_nodes= GetIcosaNum(steps); double **x= gen_syst_3d(steps); if (!x) return; pImg2.SetData(); int k; for(k= 0; k < num_nodes; k++) { double x1[3], x2[3]; x1[0]= x[k][0]; x1[1]= cos(lattitude0) * x[k][1] - sin(lattitude0) * x[k][2]; x1[2]= sin(lattitude0) * x[k][1] + cos(lattitude0) * x[k][2]; x2[0]= cos(longitude0) * x1[0] - sin(longitude0) * x1[1]; x2[1]= sin(longitude0) * x1[0] + cos(longitude0) * x1[1]; x2[2]= x1[2]; double lattitude= asin(x2[2]); double longitude= atan2(x2[1],x2[0]); pImg1.SetData(I.data); Erode3DLin(pImg1,num,lattitude,longitude); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); delete[] x[0]; delete[] x; } template void Close3DLinN (Image& I, int num, int steps, double lattitude0= 0.0, double longitude0= 0.0) { Img pImg1(I); Img pImg2(I); int num_nodes= GetIcosaNum(steps); double **x= gen_syst_3d(steps); if (!x) return; // pImg2.SetData(IL_GU_SET,(F)std::numeric_limits::max()); pImg2.SetData(); int k; for(k= 0; k < num_nodes; k++) { double x1[3], x2[3]; x1[0]= x[k][0]; x1[1]= cos(lattitude0) * x[k][1] - sin(lattitude0) * x[k][2]; x1[2]= sin(lattitude0) * x[k][1] + cos(lattitude0) * x[k][2]; x2[0]= cos(longitude0) * x1[0] - sin(longitude0) * x1[1]; x2[1]= sin(longitude0) * x1[0] + cos(longitude0) * x1[1]; x2[2]= x1[2]; double lattitude= asin(x2[2]); double longitude= atan2(x2[1],x2[0]); pImg1.SetData(I.data); Close3DLin(pImg1,num,lattitude,longitude); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); delete[] x[0]; delete[] x; } template void Open3DLinN (Image& I, int num, int steps, double lattitude0= 0.0, double longitude0= 0.0) { Img pImg1(I); Img pImg2(I); int num_nodes= GetIcosaNum(steps); double **x= gen_syst_3d(steps); if (!x) return; pImg2.SetData(); int k; for(k= 0; k < num_nodes; k++) { double x1[3], x2[3]; x1[0]= x[k][0]; x1[1]= cos(lattitude0) * x[k][1] - sin(lattitude0) * x[k][2]; x1[2]= sin(lattitude0) * x[k][1] + cos(lattitude0) * x[k][2]; x2[0]= cos(longitude0) * x1[0] - sin(longitude0) * x1[1]; x2[1]= sin(longitude0) * x1[0] + cos(longitude0) * x1[1]; x2[2]= x1[2]; double lattitude= asin(x2[2]); double longitude= atan2(x2[1],x2[0]); pImg1.SetData(I.data); Open3DLin(pImg1,num,lattitude,longitude); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); delete[] x[0]; delete[] x; } template void Dilate3DSurf2 (Image& I, int num, double lattitude, double longitude) { double lattitude1= 0.0; double longitude1= longitude + M_PI_2; double lattitude2= lattitude - M_PI_2; double longitude2= longitude; Dilate3DLin(I, num, lattitude1, longitude1); Dilate3DLin(I, num, lattitude2, longitude2); } template void Erode3DSurf2 (Image& I, int num, double lattitude, double longitude) { double lattitude1= 0.0; double longitude1= longitude + M_PI_2; double lattitude2= lattitude - M_PI_2; double longitude2= longitude; Erode3DLin(I, num, lattitude1, longitude1); Erode3DLin(I, num, lattitude2, longitude2); } template void Dilate3DSurf (Image& I, int num, double lattitude0, double longitude0) { int k; for(k= 0; k < 3; k++) { double x[3], x1[3], x2[3]; double angle= k * M_PI / 3.0; x[0]= cos(angle); x[1]= sin(angle); x[2]= 0.0; x1[0]= x[0]; x1[1]= cos(lattitude0) * x[1] - sin(lattitude0) * x[2]; x1[2]= sin(lattitude0) * x[1] + cos(lattitude0) * x[2]; x2[0]= cos(longitude0) * x1[0] - sin(longitude0) * x1[1]; x2[1]= sin(longitude0) * x1[0] + cos(longitude0) * x1[1]; x2[2]= x1[2]; double lattitude= asin(x2[2]); double longitude= atan2(x2[1],x2[0]); Dilate3DLin(I, num, lattitude, longitude); } } template void Erode3DSurf (Image& I, int num, double lattitude0, double longitude0) { double x[3][3]; int k; for (k= 0; k < 3; k++) { double angle= k * M_PI / 3.0; x[k][0]= cos(angle); x[k][1]= sin(angle); x[k][2]= 0.0; } for(k= 0; k < 3; k++) { double x1[3], x2[3]; x1[0]= x[k][0]; x1[1]= cos(lattitude0) * x[k][1] - sin(lattitude0) * x[k][2]; x1[2]= sin(lattitude0) * x[k][1] + cos(lattitude0) * x[k][2]; x2[0]= cos(longitude0) * x1[0] - sin(longitude0) * x1[1]; x2[1]= sin(longitude0) * x1[0] + cos(longitude0) * x1[1]; x2[2]= x1[2]; double lattitude= asin(x2[2]); double longitude= atan2(x2[1],x2[0]); Erode3DLin(I, num, lattitude, longitude); } } template void Close3DSurf (Image& I, int num, double lattitude, double longitude) { Dilate3DSurf(I, num, lattitude, longitude); Erode3DSurf(I, num, lattitude, longitude); } template void Open3DSurf (Image& I, int num, double lattitude, double longitude) { Erode3DSurf(I, num, lattitude, longitude); Dilate3DSurf(I, num, lattitude, longitude); } template void Dilate3DSurfN(Image& I, int num, int steps, double lattitude0= 0.0, double longitude0= 0.0) { Img pImg1(I); Img pImg2(I); int num_nodes= GetIcosaNum(steps); double **x= gen_syst_3d(steps); if (!x) return; pImg2.SetData(IL_GU_SET,(F)std::numeric_limits::max()); int k; for(k= 0; k < num_nodes; k++) { double x1[3], x2[3], pangle; x1[0]= x[k][0]; x1[1]= cos(lattitude0) * x[k][1] - sin(lattitude0) * x[k][2]; x1[2]= sin(lattitude0) * x[k][1] + cos(lattitude0) * x[k][2]; x2[0]= cos(longitude0) * x1[0] - sin(longitude0) * x1[1]; x2[1]= sin(longitude0) * x1[0] + cos(longitude0) * x1[1]; x2[2]= x1[2]; double lattitude= asin(x2[2]); double longitude= atan2(x2[1],x2[0]); pImg1.SetData(I.data); Dilate3DSurf(pImg1,num,lattitude,longitude); pImg2.SetData(IL_GB_MIN,pImg1.data); } I.SetData(pImg2.data); delete[] x[0]; delete[] x; } template void Erode3DSurfN (Image& I, int num, int steps, double lattitude0= 0.0, double longitude0= 0.0) { Img pImg1(I); Img pImg2(I); int num_nodes= GetIcosaNum(steps); double **x= gen_syst_3d(steps); if (!x) return; pImg2.SetData(); int k; for(k= 0; k < num_nodes; k++) { double x1[3], x2[3], pangle; x1[0]= x[k][0]; pangle= lattitude0; x1[1]= cos(pangle) * x[k][1] - sin(pangle) * x[k][2]; x1[2]= sin(pangle) * x[k][1] + cos(pangle) * x[k][2]; pangle= longitude0; x2[0]= cos(pangle) * x1[0] - sin(pangle) * x1[1]; x2[1]= sin(pangle) * x1[0] + cos(pangle) * x1[1]; x2[2]= x1[2]; double lattitude= asin(x2[2]); double longitude= atan2(x2[1],x2[0]); pImg1.SetData(I.data); Erode3DSurf(pImg1,num,lattitude,longitude); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); delete[] x[0]; delete[] x; } template void Close3DSurfN (Image& I, int num, int steps, double lattitude0= 0.0, double longitude0= 0.0) { Img pImg1(I); Img pImg2(I); int num_nodes= GetIcosaNum(steps); double **x= gen_syst_3d(steps); if (!x) return; // pImg2.SetData(IL_GU_SET,(F)std::numeric_limits::max()); pImg2.SetData(); int k; for(k= 0; k < num_nodes; k++) { double x1[3], x2[3], pangle; x1[0]= x[k][0]; pangle= lattitude0; x1[1]= cos(pangle) * x[k][1] - sin(pangle) * x[k][2]; x1[2]= sin(pangle) * x[k][1] + cos(pangle) * x[k][2]; pangle= longitude0; x2[0]= cos(pangle) * x1[0] - sin(pangle) * x1[1]; x2[1]= sin(pangle) * x1[0] + cos(pangle) * x1[1]; x2[2]= x1[2]; double lattitude= asin(x2[2]); double longitude= atan2(x2[1],x2[0]); pImg1.SetData(I.data); Close3DSurf(pImg1,num,lattitude,longitude); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); delete[] x[0]; delete[] x; } template void Open3DSurfN (Image& I, int num, int steps, double lattitude0= 0.0, double longitude0= 0.0) { Img pImg1(I); Img pImg2(I); int num_nodes= GetIcosaNum(steps); double **x= gen_syst_3d(steps); if (!x) return; pImg2.SetData(); int k; for(k= 0; k < num_nodes; k++) { double x1[3], x2[3], pangle; x1[0]= x[k][0]; pangle= lattitude0; x1[1]= cos(pangle) * x[k][1] - sin(pangle) * x[k][2]; x1[2]= sin(pangle) * x[k][1] + cos(pangle) * x[k][2]; pangle= longitude0; x2[0]= cos(pangle) * x1[0] - sin(pangle) * x1[1]; x2[1]= sin(pangle) * x1[0] + cos(pangle) * x1[1]; x2[2]= x1[2]; double lattitude= asin(x2[2]); double longitude= atan2(x2[1],x2[0]); pImg1.SetData(I.data); Open3DSurf(pImg1,num,lattitude,longitude); pImg2.SetData(IL_GB_MAX,pImg1.data); } I.SetData(pImg2.data); delete[] x[0]; delete[] x; } template void movavg3D_lin (F* src, int width, int height, int depth, int n, int dir, double ddx, double ddy, F* buf) { int i, j, k, i0, l; int Ssize= width * height; int size= Ssize * depth; F *p, *q, *r, *t, *u, *v; double dx, dy; if (n < 1) return; memcpy(buf, src, size * sizeof(F)); switch(dir) { case x_dir: { //forward for (j= 1, r= src + 1, dx= ddx, dy= ddy, k= 1; j < width; j++, dx+= ddx, dy+= ddy, r++) { int dp= 0; int dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp+= width; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq+= width; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= Ssize; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= Ssize; } else l= 0; if (k > n) k= 1; else { for (t= r + dp, u= r - 1 + dq; l < depth; l++, t+= Ssize, u+= Ssize) for (i= i0, p= t, q= u; i < height; i++, p+= width, q+= width) *p+= *q; k++; } } //backward r= buf + width - 2; dx-= 2.0 * ddx; dy-= 2.0 * ddy; k= (width - 1) % (n + 1); for (j= 1; j < width; j++, dx-= ddx, dy-= ddy, r--) { int dp= 0; int dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp+= width; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq+= width; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= Ssize; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= Ssize; } else l= 0; if (k < 1) k= n; else { for (t= r + dp, u= r + 1 + dq; l < depth; l++, t+= Ssize, u+= Ssize) for (i= i0, p= t, q= u; i < height; i++, p+= width, q+= width) *p+= *q; k--; } } //join forward double dx1, dx2, dy1, dy2; int np= n - n / 2; int nr= n - np; dx1= 0.0; dx= np * ddx; dx2= n * ddx; dy1= 0.0; dy= np * ddy; dy2= n * ddy; for (j= n, k= 1; j < width; j++, dx1+= ddx, dx+= ddx, dx2+= ddx, dy1+= ddy, dy+= ddy, dy2+= ddy) { //TODO optimize ptrdiff_t n0; int dp= 0; int dq= 0; int dr= 0; if (ddx < 0) { n0= ptrdiff_t(floor(dx2+0.5)); dq+= width * (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx1+0.5)) - n0; dr+= i0 * width; } else { n0= ptrdiff_t(floor(dx1+0.5)); dq+= width * (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx2+0.5)) - n0; dp+= i0 * width; } if (ddy < 0) { n0= ptrdiff_t(floor(dy2+0.5)); dq+= Ssize * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy1+0.5)) - n0; dr+= l * Ssize; } else { n0= ptrdiff_t(floor(dy1+0.5)); dq+= Ssize * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy2+0.5)) - n0; dp+= l * Ssize; } if (k == 1) for (u= src + j - nr + dq, v= src + j + dp; l < depth; l++, u+= Ssize, v+= Ssize) for (i= i0, q= u, p= v; i < height; i++, p+= width, q+= width) *q= *p; else for (t= buf + j - n + dr, u= src + j - nr + dq, v= src + j + dp; l < depth; l++, t+= Ssize, u+= Ssize, v+= Ssize) for (i= i0, r= t, q= u, p= v; i < height; i++, p+= width, q+= width, r+= width) *q= *r + *p; if (k > n) k= 1; else k++; } } break; case y_dir:{ //forward for (j= 1, r= src + width, dx= ddx, dy= ddy, k= 1; j < height; j++, dx+= ddx, dy+= ddy, r+= width) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp++; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq++; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= Ssize; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= Ssize; } else l= 0; if (k > n) k= 1; else { for (t= r + dp, u= r - width + dq; l < depth; l++, t+= Ssize, u+= Ssize) for (i= i0, p= t, q= u; i < width; i++, p++, q++) *p+= *q; k++; } } //backward r= buf + width * (height - 2); dx-= 2.0 * ddx; dy-= 2.0 * ddy; k= (height - 1) % (n + 1); for (j= 1; j < height; j++, dx-= ddx, dy-= ddy, r-= width) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp++; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq++; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= Ssize; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= Ssize; } else l= 0; if (k < 1) k= n; else { for (t= r + dp, u= r + width + dq; l < depth; l++, t+= Ssize, u+= Ssize) for (i= i0, p= t, q= u; i < width; i++, p++, q++) *p+= *q; k--; } } //join forward double dx1, dx2, dy1, dy2; int np= n - n / 2; int nr= n - np; dx1= 0.0; dx= np * ddx; dx2= n * ddx; dy1= 0.0; dy= np * ddy; dy2= n * ddy; for (j= n, k= 1; j < height; j++, dx1+= ddx, dx+= ddx, dx2+= ddx, dy1+= ddy, dy+= ddy, dy2+= ddy) { //TODO optimize ptrdiff_t n0; ptrdiff_t dp= 0; ptrdiff_t dq= 0; ptrdiff_t dr= 0; if (ddx < 0) { n0= ptrdiff_t(floor(dx2+0.5)); dq+= (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx1+0.5)) - n0; dr+= i0; } else { n0= ptrdiff_t(floor(dx1+0.5)); dq+= (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx2+0.5)) - n0; dp+= i0; } if (ddy < 0) { n0= ptrdiff_t(floor(dy2+0.5)); dq+= Ssize * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy1+0.5)) - n0; dr+= l * Ssize; } else { n0= ptrdiff_t(floor(dy1+0.5)); dq+= Ssize * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy2+0.5)) - n0; dp+= l * Ssize; } if (k == 1) for (u= src + width * (j - nr) + dq, v= src + width * j + dp; l < depth; l++, u+= Ssize, v+= Ssize) for (i= i0, q= u, p= v; i < width; i++, p++, q++) *q= *p; else for (t= buf + width * (j - n) + dr, u= src + width * (j - nr) + dq, v= src + width * j + dp; l < depth; l++, t+= Ssize, u+= Ssize, v+= Ssize) for (i= i0, r= t, q= u, p= v; i < width; i++, p++, q++, r++) *q= *r + *p; if (k > n) k= 1; else k++; } } break; case z_dir:{ //forward for (j= 1, r= src + Ssize, dx= ddx, dy= ddy, k= 1; j < depth; j++, dx+= ddx, dy+= ddy, r+= Ssize) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp++; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq++; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= width; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= width; } else l= 0; if (k > n) k= 1; else { for (t= r + dp, u= r - Ssize + dq; l < height; l++, t+= width, u+= width) for (i= i0, p= t, q= u; i < width; i++, p++, q++) *p+= *q; k++; } } //backward r= buf + Ssize * (depth - 2); dx-= 2.0 * ddx; dy-= 2.0 * ddy; k= (depth - 1) % (n + 1); for (j= 1; j < depth; j++, dx-= ddx, dy-= ddy, r-= Ssize) { ptrdiff_t dp= 0; ptrdiff_t dq= 0; if (dx >= 0.5) { dx-= 1.0; i0= 1; dp++; } else if (dx < -0.5) { dx+= 1.0; i0= 1; dq++; } else i0= 0; if (dy >= 0.5) { dy-= 1.0; l= 1; dp+= width; } else if (dy < -0.5) { dy+= 1.0; l= 1; dq+= width; } else l= 0; if (k < 1) k= n; else { for (t= r + dp, u= r + Ssize + dq; l < height; l++, t+= width, u+= width) for (i= i0, p= t, q= u; i < width; i++, p++, q++) *p+= *q; k--; } } //join forward double dx1, dx2, dy1, dy2; int np= n - n / 2; int nr= n - np; dx1= 0.0; dx= np * ddx; dx2= n * ddx; dy1= 0.0; dy= np * ddy; dy2= n * ddy; for (j= n, k= 1; j < depth; j++, dx1+= ddx, dx+= ddx, dx2+= ddx, dy1+= ddy, dy+= ddy, dy2+= ddy) { //TODO optimize ptrdiff_t n0; ptrdiff_t dp= 0; ptrdiff_t dq= 0; ptrdiff_t dr= 0; if (ddx < 0) { n0= ptrdiff_t(floor(dx2+0.5)); dq+= (ptrdiff_t(floor(dx+0.5)) - n0); i0= n0 - ptrdiff_t(floor(dx1+0.5)); dr+= i0; } else { n0= ptrdiff_t(floor(dx1+0.5)); dq+= (ptrdiff_t(floor(dx+0.5)) - n0); i0= ptrdiff_t(floor(dx2+0.5)) - n0; dp+= i0; } if (ddy < 0) { n0= ptrdiff_t(floor(dy2+0.5)); dq+= width * (ptrdiff_t(floor(dy+0.5)) - n0); l= n0 - ptrdiff_t(floor(dy1+0.5)) - n0; dr+= l * width; } else { n0= ptrdiff_t(floor(dy1+0.5)); dq+= width * (ptrdiff_t(floor(dy+0.5)) - n0); l= ptrdiff_t(floor(dy2+0.5)) - n0; dp+= l * width; } if (k == 1) for (u= src + Ssize * (j - nr) + dq, v= src + Ssize * j + dp; l < height; l++, u+= width, v+= width) for (i= i0, q= u, p= v; i < width; i++, p++, q++) *q= *p; else for (t= buf + Ssize * (j - n) + dr, u= src + Ssize * (j - nr) + dq, v= src + Ssize * j + dp; l < height; l++, t+= width, u+= width, v+= width) for (i= i0, r= t, q= u, p= v; i < width; i++, p++, q++, r++) *q= *r + *p; if (k > n) k= 1; else k++; } } break; } } template void MovAvg3DLin (Image& I, int num, double lattitude, double longitude) { ptrdiff_t i, j; F *q; if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; Image pImg(3,I.dims); F *pdat= new F[step]; int n1, n2, n3, rot; double di1, di2; getlinpar3d(I.Dx(0), I.Dx(1), I.Dx(2), num, lattitude, longitude, n1, n2, n3, rot, di1, di2); for (i= 0; i < numslic; i++) { movavg3D_lin (q, I.dims[0], I.dims[1], I.dims[2], n1, rot, di1, di2, pdat); pImg.data= q; pImg.SetData(IL_GU_DIV,n1); q+= step; } delete [] pdat; } template void MovAvg3DLin (Image& I, int num, double lattitude, double longitude) { ptrdiff_t i, j; F *q; if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; Img pImg(3,I.dims); G *pdat= new G[step]; int n1, n2, n3, rot; double di1, di2; getlinpar3d(I.Dx(0), I.Dx(1), I.Dx(2), num, lattitude, longitude, n1, n2, n3, rot, di1, di2); for (i= 0; i < numslic; i++) { pImg.SetData(q); movavg3D_lin (pImg.data, I.dims[0], I.dims[1], I.dims[2], n1, rot, di1, di2, pdat); pImg.SetData(IL_GU_DIV,n1); q+= step; } delete [] pdat; } #undef x_dir #undef y_dir #undef z_dir template void MovAvg3DSurf2 (Image& I, int num, double lattitude, double longitude) { double lattitude1= 0.0; double longitude1= longitude + M_PI_2; double lattitude2= lattitude - M_PI_2; double longitude2= longitude; MovAvg3DLin(I, num, lattitude1, longitude1); MovAvg3DLin(I, num, lattitude2, longitude2); } template void MovAvg3DSurf2 (Image& I, int num, double lattitude, double longitude) { double lattitude1= 0.0; double longitude1= longitude + M_PI_2; double lattitude2= lattitude - M_PI_2; double longitude2= longitude; MovAvg3DLin(I, num, lattitude1, longitude1); MovAvg3DLin(I, num, lattitude2, longitude2); } template void MovAvg3DSurf (Image& I, int num, double lattitude, double longitude) { int k; for(k= 0; k < 3; k++) { double x[3], x1[3], x2[3]; double angle= k * M_PI / 3.0; x[0]= cos(angle); x[1]= sin(angle); x[2]= 0.0; x1[0]= x[0]; x1[1]= cos(lattitude0) * x[1] - sin(lattitude0) * x[2]; x1[2]= sin(lattitude0) * x[1] + cos(lattitude0) * x[2]; x2[0]= cos(longitude0) * x1[0] - sin(longitude0) * x1[1]; x2[1]= sin(longitude0) * x1[0] + cos(longitude0) * x1[1]; x2[2]= x1[2]; double lattitude= asin(x2[2]); double longitude= atan2(x2[1],x2[0]); MovAvg3DLin(I, num, lattitude, longitude); } } template void MovAvg3DSurf (Image& I, int num, double lattitude, double longitude) { int k; for(k= 0; k < 3; k++) { double x[3], x1[3], x2[3]; double angle= k * M_PI / 3.0; x[0]= cos(angle); x[1]= sin(angle); x[2]= 0.0; x1[0]= x[0]; x1[1]= cos(lattitude0) * x[1] - sin(lattitude0) * x[2]; x1[2]= sin(lattitude0) * x[1] + cos(lattitude0) * x[2]; x2[0]= cos(longitude0) * x1[0] - sin(longitude0) * x1[1]; x2[1]= sin(longitude0) * x1[0] + cos(longitude0) * x1[1]; x2[2]= x1[2]; double lattitude= asin(x2[2]); double longitude= atan2(x2[1],x2[0]); MovAvg3DLin(I, num, lattitude, longitude); } } //Gray reconstruction in 1d, 2d and 3d*************************************************************** template void reconstruct_gray_1d(F *dt, G *idt, ptrdiff_t width) { F *i1; G *j1; F p; ptrdiff_t j; i1= dt; j1= idt; p= *i1; for (j= 0; j < width; j++, i1++, j1++) { if (p < *i1) p= *i1; if (p < *j1) *i1= p; else { *i1= *j1; p= *i1; } } i1= dt + width - 1; j1= idt + width - 1; p= *i1; for (j= 0; j < width; j++, i1--, j1--) { if (p < *i1) p= *i1; if (p < *j1) *i1= p; else { *i1= *j1; p= *i1; } } } template void reconstruct_gray_2d_4(F *dt, G *idt, ptrdiff_t width, ptrdiff_t height, recmod mode) { F *i0, *i1, *i2; G *j0, *j1, *j2; F p, p1, p2; ptrdiff_t i, j, k; ptrdiff_t size= width * height; Stack2UInt stck; #define TEST \ if (p < *i1) p= *i1; \ if (p < *i2) p= *i2; \ if (p < *j1) *i1= p; \ else { *i1= *j1; p= *i1; } #define INIP(dely) \ i1= i0; \ i2= i0 + (dely); \ j1= j0; \ j2= j0 + (dely); \ p= *i0; #define INCP \ i1++; i2++; j1++; #define STEP1(dy) \ INIP(dy) \ for (j= 0; j < width; j++) { \ TEST \ INCP \ } \ i0+= width; j0+= width; i0= dt; j0= idt; STEP1(0) for (i= 1; i < height; i++) { STEP1(-width) } #undef INCP #undef STEP1 #define TESTS \ if (((p1 < p)&&(p1 < p2))||((*i2 < p)&&(*i2 < *j2))) { \ stck.Push(j, i); \ } #define DECP \ i1--; i2--; j1--; j2--; #define STEP2(dy) \ INIP(dy) \ p2= *j0; \ for (j= width - 1; j >= 0; j--) { \ p1= p; \ TEST \ TESTS \ p2= *j1; \ DECP \ } \ i0-= width; j0-= width; i0= dt + size - 1; j0= idt + size - 1; i= height - 1; STEP2(0) for (i= height - 2; i >= 0; i--) { STEP2(width) } #undef TEST #undef TESTS #undef INIP #undef DECP #undef STEP2 #define PPoint(j, i) \ k= (j) + width * (i); \ i2= dt + k; \ if (*i2 < *i1) { \ p= *(idt + k); \ if (*i2 < p) { \ if (p <= *i1) *i2= p; \ else *i2= *i1; \ stck.Push(j, i); \ } \ } if (mode == rectot) while (stck.Pop(j, i)) { k= j + width * i; i1= dt + k; j1= idt + k; if (j > 0) { PPoint(j - 1, i) } if (j < (width - 1)) { PPoint(j + 1, i) } if (i > 0) { PPoint(j, i - 1) } if (i < (height - 1)) { PPoint(j, i + 1) } } #undef PPoint } template void reconstruct_gray_2d_8(F *dt, G *idt, ptrdiff_t width, ptrdiff_t height, recmod mode) { F *i0, *i1, *i2; G *j0, *j1, *j2; ptrdiff_t size= width * height; F p, p1, p2, p3, p4, q1, q2, q3; ptrdiff_t i, j, k; Stack2UInt stck; #define TEST \ if (p1 < *i1) p1= *i1; \ if (p1 < *i2) p1= *i2; \ if (p1 < p2) p1= p2; \ if (p1 < p3) p1= p3; \ if (p1 < *j1) *i1= p1; \ else { *i1= *j1; p1= *i1; } #define INIP(dely) \ i1= i0; \ i2= i0 + (dely); \ j1= j0; \ p1= *i0; \ p2= *i2; p3= p2; i2++; #define CP(op1,op2) \ i1 op1; \ p3= p2; p2= *i2; i2 op2; \ j1 op1; #define STEP1(dy) \ INIP(dy) \ for (j= 2; j < width; j++) { \ TEST \ CP(++,++) \ } \ TEST \ CP(++,) \ TEST \ i0+= width; j0+= width; i0= dt; j0= idt; STEP1(0) for (i= 1; i < height; i++) { STEP1(-width) } #undef STEP1 #define CQ(op) \ q1= *j1; \ q3= q2; q2= *j2; j2 op; #define INIQ(dely) \ i1= i0; \ i2= i0 + (dely); \ j1= j0; \ j2= j0 + (dely); \ p1= *i0; \ p2= *i2; p3= p2; i2--; \ q1= *j0; \ q2= *j2; q3= q2; j2--; #define TESTS \ if (((p4 < p1)&&(p4 < q1)) \ ||((p2 < p1)&&(p2 < q2))||((p3 < p1)&&(p3 < q3)) \ ||((*i2 < p1)&&(*i2 < *j2))) { \ stck.Push(j,i); \ } #define STEP2(dy) \ INIQ(dy) \ for (j= width - 1; j > 1; j--) { \ p4= p1; \ TEST \ TESTS \ CQ(--) \ CP(--,--) \ } \ j= 1; p4= p1; \ TEST \ TESTS \ CQ() \ CP(--,) \ j= 0; p4= p1; \ TEST \ TESTS \ i0-= width; j0-= width; i0= dt + size - 1; j0= idt + size - 1; i= height - 1; STEP2(0) for (i= height - 2; i >= 0; i--) { STEP2(width) } #undef TEST #undef TESTS #undef INIP #undef INIQ #undef CP #undef CQ #undef STEP2 #undef CASE #define PPoint(j, i) \ k= (j) + width * (i); \ i2= dt + k; \ if (*i2 < *i1) { \ p= *(idt + k); \ if (*i2 < p) { \ if (p <= *i1) *(i2)= p; \ else *i2= *i1; \ stck.Push(j, i); \ } \ } if (mode == rectot) while (stck.Pop(j, i)) { k= j + width * i; \ i1= dt + k; j1= idt + k; if (j > 0) { PPoint(j - 1, i) } if (j < (width - 1)) { PPoint(j + 1, i) } if (i > 0) { PPoint(j, i - 1) } if (i < (height - 1)) { PPoint(j, i + 1) } if (j > 0) { if (i > 0) { PPoint(j - 1, i - 1) } if (i < (height - 1)) { PPoint(j - 1, i + 1) } } if (j < (width - 1)) { if (i > 0) { PPoint(j + 1, i - 1) } if (i < (height - 1)) { PPoint(j + 1, i + 1) } } } #undef PPoint } template void reconstruct_gray_3d_6(F *dt, G *idt, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, recmod mode) { F *i0, *i1, *i2, *i00, *i01, *i10; G *j0, *j1, *j00, *j01, *j10; ptrdiff_t sizeg= width * height; F p, p1, p2; ptrdiff_t i, j, k, l; Queue3UInt que; #define TEST \ if (p < *i00) p= *i00; \ if (p < *i01) p= *i01; \ if (p < *i10) p= *i10; \ if (p < *j00) *i00= p; \ else { *i00= *j00; p= *i00; } #define INIP(dely,delz) \ i00= i0; \ i01= i0 + (dely); \ i10= i0 + (delz); \ j00= j0; \ j01= j0 + (dely); \ j10= j0 + (delz); \ p= *i00; #define INCP \ i00++; i01++; i10++; j00++; #define STEP1(dy,dz) \ INIP(dy,dz) \ for (j= 0; j < width; j++) { \ TEST \ INCP \ } \ i0+= width; j0+= width; i0= dt; j0= idt; STEP1(0,0) for (i= 1; i < height; i++) { STEP1(-width,0) } for(k= 1; k < depth; k++) { STEP1(0,-sizeg) for (i= 1; i < height; i++) { STEP1(-width,-sizeg) } } #undef INCP #undef STEP1 #define DECP \ i00--; i01--; i10--; \ j00--; j01--; j10--; #define TESTS \ if (((p1 < p)&&(p1 < p2)) \ ||((*i01 < p)&&(*i01 < *j01)) \ ||((*i10 < p)&&(*i10 < *j10))) { \ que.Push(j,i,k); \ } #define STEP2(dy,dz) \ INIP(dy,dz) \ p2= *j0; \ for (j= width - 1; j >= 0; j--) { \ p1= p; \ TEST \ TESTS \ p2= *j00; \ DECP \ } \ i0-= width; j0-= width; i0= dt + sizeg * depth - 1; j0= idt + sizeg * depth - 1; k= depth - 1; i= height - 1; STEP2(0,0) for (i= height - 2; i >= 0; i--) { STEP2(width,0) } for(k= depth - 2; k >= 0; k--) { i= height - 1; STEP2(0,sizeg) for (i= height - 2; i >= 0; i--) { STEP2(width,sizeg) } } #undef TEST #undef TESTS #undef INIP #undef DECP #undef STEP2 #define PPoint(j,i,k) \ l= (j) + width * (i) + sizeg * (k); \ i2= dt + l; \ if (*i2 < *i1) { \ p= *(idt + l); \ if (*i2 < p) { \ if (p <= *i1) *i2= p; \ else *i2= *i1; \ que.Push(j, i, k); \ } \ } if (mode == rectot) while (que.Pop(j, i, k)) { l= j + width * i + sizeg * k; i1= dt + l; j1= idt + l; if (j > 0) { PPoint(j - 1, i, k) } if (j < (width - 1)) { PPoint(j + 1, i, k) } if (i > 0) { PPoint(j, i - 1, k) } if (i < (height - 1)) { PPoint(j, i + 1, k) } if (k > 0) { PPoint(j, i, k - 1); } if (k < (depth - 1)) { PPoint(j, i, k + 1) } } #undef PPoint } template void reconstruct_gray_3d_18(F *dt, G *idt, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, recmod mode) { F *i0, *i1, *i2, *i00, *i01, *i10, *i11, *i12; G *j0, *j1, *j00, *j01, *j10, *j11, *j12; ptrdiff_t sizeg= width * height; F p, p00, p01, q01, p10, q10, r00, r01, s01, r10, s10; ptrdiff_t i, j, k, l; Queue3UInt que; #define TEST \ if (p00 < *i00) p00= *i00; \ if (p00 < *i01) p00= *i01; \ if (p00 < p01) p00= p01; \ if (p00 < q01) p00= q01; \ if (p00 < *i10) p00= *i10; \ if (p00 < p10) p00= p10; \ if (p00 < q10) p00= q10; \ if (p00 < *i11) p00= *i11; \ if (p00 < *i12) p00= *i12; \ if (p00 < *j00) *i00= p00; \ else { *i00= *j00; p00= *i00; } #define INIP(dely,delz) \ i00= i0; \ p00= *i00; \ i01= i0 + (dely); \ p01= *i01; q01= p01; i01++; \ i10= i0 + (delz); \ p10= *i10; q10= p10; i10++; \ i11= i0 + (dely) + (delz); \ i12= i0 - (dely) + (delz); \ j00= j0; #define CP(op1,op2) \ i00 op1; \ q01= p01; p01=*i01; i01 op2; \ q10= p10; p10=*i10; i10 op2; \ i11 op1; i12 op1; \ j00 op1; #define STEP1(dy,dz) \ INIP(dy,dz) \ for (j= 2; j < width; j++) { \ TEST \ CP(++,++) \ } \ TEST \ CP(++) \ TEST \ i0+= width; j0+= width; i0= dt; j0= idt; STEP1(0,0) for (i= 1; i < height; i++) { STEP1(-width,0) } for(k= 1; k < depth; k++) { STEP1(0,-sizeg) for (i= 1; i < height; i++) { STEP1(-width,-sizeg) } } #undef INIP #undef STEP1 #define CR(op) \ r00= *j00; \ s01= r01; r01= *j01; j01 op; \ s10= r10; r10= *j10; j10 op; \ j11--; j12--; #define TESTS \ if (((p < p00)&&(p < r00)) \ ||((*i01 < p00)&&(*i01 < *j01)) \ ||((p01 < p00)&&(p01 < r01)) \ ||((q01 < p00)&&(q01 < s01)) \ ||((*i10 < p00)&&(*i10 < *j10)) \ ||((p10 < p00)&&(p10 < r10)) \ ||((q10 < p00)&&(q10 < s10)) \ ||((*i11 < p00)&&(*i11 < *j11)) \ ||((*i12 < p00)&&(*i12 < *j12))) { \ que.Push(j,i,k); \ } #define INIR(dely,delz) \ i00= i0; \ p00= *i00; \ i01= i0 + (dely); \ p01= *i01; q01= p01; i01--; \ i10= i0 + (delz); \ p10= *i10; q10= p10; i10--; \ i11= i0 + (dely) + (delz); \ i12= i0 - (dely) + (delz); \ j00= j0; \ r00= *j00; \ j01= j0 + (dely); \ r01= *j01; s01= r01; j01--; \ j10= j0 + (delz); \ r10= *j10; s10= r10; j10--; \ j11= j0 + (dely) + (delz); \ j12= j0 - (dely) + (delz); #define STEP2(dy,dz) \ INIR(dy,dz) \ for (j= width - 1; j > 1; j--) { \ p= p00; \ TEST \ TESTS \ CR(--) \ CP(--,--) \ } \ j= 1; p= p00; \ TEST \ TESTS \ CR() \ CP(--,) \ j= 0; p= p00; \ TEST \ TESTS \ i0-= width; j0-= width; i0= dt + sizeg * depth - 1; j0= idt + sizeg * depth - 1; k= depth - 1; i= height - 1; STEP2(0,0) for (i= height - 2; i >= 0; i--) { STEP2(width,0) } for(k= depth - 2; k >= 0; k--) { i= height - 1; STEP2(0,sizeg) for (i= height - 2; i >= 0; i--) { STEP2(width,sizeg) } } #undef TEST #undef TESTS #undef INIR #undef CP #undef CR #undef STEP2 #define PPoint(j,i,k) \ l= (j) + width * (i) + sizeg * (k); \ i2= dt + l; \ if (*i2 < *i1) { \ p= *(idt + l); \ if (*i2 < p) { \ if (p <= *i1) *i2= p; \ else *i2= *i1; \ que.Push(j, i, k); \ } \ } if (mode == rectot) while (que.Pop(j, i, k)) { l= j + width * i + sizeg * k; i1= dt + l; j1= idt + l; if (j > 0) { PPoint(j - 1, i, k) } if (j < (width - 1)) { PPoint(j + 1, i, k) } if (i > 0) { PPoint(j, i - 1, k) if (j > 0) { PPoint(j - 1, i - 1, k) } if (j < (width - 1)) { PPoint(j + 1, i - 1, k) } } if (i < (height - 1)) { PPoint(j, i + 1, k) if (j > 0) { PPoint(j - 1, i + 1, k) } if (j < (width - 1)) { PPoint(j + 1, i + 1, k) } } if (k > 0) { PPoint(j, i, k - 1) if (j > 0) { PPoint(j - 1, i, k - 1) } if (j < (width - 1)) { PPoint(j + 1, i, k - 1) } if (i > 0) { PPoint(j, i - 1, k - 1) } if (i < (height - 1)) { PPoint(j, i + 1, k - 1) } } if (k < (depth - 1)) { PPoint(j, i, k + 1) if (j > 0) { PPoint(j - 1, i, k + 1) } if (j < (width - 1)) { PPoint(j + 1, i, k + 1) } if (i > 0) { PPoint(j, i - 1, k + 1) } if (i < (height - 1)) { PPoint(j, i + 1, k + 1) } } } #undef PPoint } template void Reconstruct1D(Image& I, Image& J) { if (!I.data || !J.data) throw Allocerr(); if (J.nDim != I.nDim) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 1, I.dims + 1); ptrdiff_t step= I.dims[0]; F* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step) reconstruct_gray_1d(q, p, I.dims[0]); } template void Reconstruct2D(Image& I, Image& J, con2D conn = con4, recmod rec = rectot) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 2) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step) if (conn == con8) reconstruct_gray_2d_8(q, p, I.dims[0], I.dims[1], rec); else reconstruct_gray_2d_4(q, p, I.dims[0], I.dims[1], rec); } template void Reconstruct3D(Image& I, Image& J, con3D conn = con6, recmod rec = rectot) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim) ) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step) if (conn == con6) reconstruct_gray_3d_6(I.data, J.data, I.dims[0], I.dims[1], I.dims[2], rec); else reconstruct_gray_3d_18(I.data, J.data, I.dims[0], I.dims[1], I.dims[2], rec); } //Lipschitz 2D and 3D template void lipschitz_2d_ch(float *fdt, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double slp) { ptrdiff_t i, j, size; float *q, *f0, *f1; double d1, d, fp, fp1, fp2, ddx, ddy, ddxy; size= width * height; ddx= dx * slp; ddy= dy * slp; ddxy= hypot(dx, dy) * slp; #define TEST \ d= fp + ddx; \ d1= *f1 + ddxy; \ if (d1 < d) { \ d= d1; \ } \ d1= fp1 + ddy; \ if (d1 < d) { \ d= d1; \ } \ d1= fp2 + ddxy; \ if (d1 < d) { \ d= d1; \ } \ if (d < *f0) { \ *f0= d; \ } #define INIP(dely,delx) \ f0= q; fp= *f0; \ f1= q + (dely); \ fp1= *f1; fp2= fp1; \ f1+= delx; #define INCP \ fp= *f0; f0++; fp2= fp1; fp1= *f1; f1++; #define INCP0 \ fp= *f0; f0++; fp2= fp1; fp1= *f1; #define DECP \ fp= *f0; f0--; fp2= fp1; fp1= *f1; f1--; #define DECP0 \ fp= *f0; f0--; fp2= fp1; fp1= *f1; q= fdt; INIP(0,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; for (i= 1; i < height; i++) { INIP(-width,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; } q= fdt + size - 1; INIP(0,-1) for (j= width - 1; j > 1; j--) { TEST DECP } TEST DECP0 TEST q-= width; for (i= height - 2; i >= 0; i--) { INIP(width,-1) for (j= width - 1; j > 1; j--) { TEST DECP } TEST DECP0 TEST q-= width; } #undef TEST #undef INIP #undef INCP #undef DECP #undef INCP0 #undef DECP0 } //with labels template void lipschitz_2d_ch(float *fdt, size_t *ldt, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double slp) { size_t *i0, *i1, *j0, p1, p2, p0, lp; ptrdiff_t i, j, size; float *q, *f0, *f1; double d1, d, fp, fp1, fp2, ddx, ddy, ddxy; size= width * height; ddx= dx * slp; ddy= dy * slp; ddxy= hypot(dx, dy) * slp; for (i= 0, i0= ldt; i < size; i++, i0++) *i0= i; #define TEST \ d= fp + ddx; \ lp= p0; \ d1= *f1 + ddxy; \ if (d1 < d) { \ lp= *i1; d= d1; \ } \ d1= fp1 + ddy; \ if (d1 < d) { \ lp= p1; d= d1; \ } \ d1= fp2 + ddxy; \ if (d1 < d) { \ lp= p2; d= d1; \ } \ if (d < *f0) { \ *i0= lp; *f0= d; \ } #define INIP(dely,delx) \ i0= j0; p0= *i0; \ i1= j0 + (dely); \ p1= *i1; p2= p1; \ i1+= delx; \ f0= q; fp= *f0; \ f1= q + (dely); \ fp1= *f1; fp2= fp1; \ f1+= delx; #define INCP \ p0= *i0; i0++; p2= p1; p1= *i1; i1++; \ fp= *f0; f0++; fp2= fp1; fp1= *f1; f1++; #define INCP0 \ p0= *i0; i0++; p2= p1; p1= *i1;\ fp= *f0; f0++; fp2= fp1; fp1= *f1; #define DECP \ p0= *i0; i0--; p2= p1; p1= *i1; i1--; \ fp= *f0; f0--; fp2= fp1; fp1= *f1; f1--; #define DECP0 \ p0= *i0; i0--; p2= p1; p1= *i1;\ fp= *f0; f0--; fp2= fp1; fp1= *f1; j0= ldt; q= fdt; INIP(0,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; j0+= width; for (i= 1; i < height; i++) { INIP(-width,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; j0+= width; } j0= ldt + size - 1; q= fdt + size - 1; INIP(0,-1) for (j= width - 1; j > 1; j--) { TEST DECP } TEST DECP0 TEST q-= width; j0-= width; for (i= height - 2; i >= 0; i--) { INIP(width,-1) for (j= width - 1; j > 1; j--) { TEST DECP } TEST DECP0 TEST q-= width; j0-= width; } #undef TEST #undef INIP #undef INCP #undef DECP #undef INCP0 #undef DECP0 } template void lipschitz_3d_ch(float *fdt, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, double slp) { ptrdiff_t i, j, k, sizeg, size; float *q, *f10, *f01, *f00, *f11, *f12; double d1, d, fp00, fp01, fq01, fp10, fq10, ddx, ddy, ddz, ddxy, ddxz, ddyz; sizeg= width * height; size= sizeg * depth; ddx= dx * slp; ddy= dy * slp; ddz= dz * slp; ddxy= sqrt(dx * dx + dy * dy) * slp; ddxz= sqrt(dx * dx + dz * dz) * slp; ddyz= sqrt(dy * dy + dz * dz) * slp; #define TEST \ d= fp00 + ddx; \ d1= *f01 + ddxy; \ if (d1 < d) { \ d= d1; \ } \ d1= fp01 + ddy; \ if (d1 < d) { \ d= d1; \ } \ d1= fq01 + ddxy; \ if (d1 < d) { \ d= d1; \ } \ d1= *f11 + ddyz; \ if (d1 < d) { \ d= d1; \ } \ d1= *f12 + ddyz; \ if (d1 < d) { \ d= d1; \ } \ d1= *f10 + ddxz; \ if (d1 < d) { \ d= d1; \ } \ d1= fp10 + ddz; \ if (d1 < d) { \ d= d1; \ } \ d1= fq10 + ddxz; \ if (d1 < d) { \ d= d1; \ } \ if (d < *f00) { \ *f00= d; \ } #define INIP(dely,delz,delzy,delx) \ f00= q; fp00= *f00; \ f01= q + (dely); fp01= *f01; fq01= fp01; f01+= delx; \ f10= q + (delz); fp10= *f10; fq10= fp10; f10+= delx; \ f11= q + (delz) + (dely); \ f12= q + (delz) + (delzy); #define INCP \ fp00= *f00; f00++; \ fq01= fp01; fp01= *f01; f01++; \ fq10= fp10; fp10= *f10; f10++; \ f11++; f12++; #define INCP0 \ fp00= *f00; f00++; \ fq01= fp01; fp01= *f01; \ fq10= fp10; fp10= *f10; \ f11++; f12++; #define DECP \ fp00= *f00; f00--; \ fq01= fp01; fp01= *f01; f01--; \ fq10= fp10; fp10= *f10; f10--; \ f11--; f12--; #define DECP0 \ fp00= *f00; f00--; \ fq01= fp01; fp01= *f01; \ fq10= fp10; fp10= *f10; \ f11--; f12--; q= fdt; INIP(0,0,width,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; for (i= 2; i < height; i++) { INIP(-width,0,width,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; } INIP(-width,0,0,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; for (k= 1; k < depth; k++) { INIP(0,-sizeg,width,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; for (i= 2; i < height; i++) { INIP(-width,-sizeg,width,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; } INIP(-width,-sizeg,0,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; } q= fdt + depth * sizeg - 1; INIP(0,0,-width,-1) for (j= 2; j < width; j++) { TEST DECP } TEST DECP0 TEST q-= width; for (i= 2; i < height; i++) { INIP(width,0,-width,-1) for (j= 2; j < width; j++) { TEST DECP } TEST DECP0 TEST q-= width; } INIP(width,0,0,-1) for (j= 2; j < width; j++) { TEST DECP } TEST DECP0 TEST q-= width; for (k= 1; k < depth; k++) { INIP(0,sizeg,-width,-1) for (j= 2; j < width; j++) { TEST DECP } TEST DECP0 TEST q-= width; for (i= 2; i < height; i++) { INIP(width,sizeg,-width,-1) for (j= 2; j < width; j++) { TEST DECP } TEST DECP0 TEST q-= width; } INIP(width,sizeg,0,-1) for (j= 2; j < width; j++) { TEST DECP } TEST DECP0 TEST q-= width; } #undef TEST #undef INIP #undef INCP #undef DECP #undef INCP0 #undef DECP0 } template void lipschitz_3d_ch(float *fdt, size_t *ldt, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, double slp) { size_t *i10, *i01, *i00, *i11, *i12, *j0, p00, p01, q01, p10, q10, lp; ptrdiff_t i, j, k, sizeg, size; float *q, *f10, *f01, *f00, *f11, *f12; double d1, d, fp00, fp01, fq01, fp10, fq10, ddx, ddy, ddz, ddxy, ddxz, ddyz; sizeg= width * height; size= sizeg * depth; ddx= dx * slp; ddy= dy * slp; ddz= dz * slp; ddxy= sqrt(dx * dx + dy * dy) * slp; ddxz= sqrt(dx * dx + dz * dz) * slp; ddyz= sqrt(dy * dy + dz * dz) * slp; for (i= 0, j0= ldt; i < size; i++, j0++) *j0= i; #define TEST \ d= fp00 + ddx; \ lp= p00; \ d1= *f01 + ddxy; \ if (d1 < d) { \ lp= *i01; d= d1; \ } \ d1= fp01 + ddy; \ if (d1 < d) { \ lp= p01; d= d1; \ } \ d1= fq01 + ddxy; \ if (d1 < d) { \ lp= q01; d= d1; \ } \ d1= *f11 + ddyz; \ if (d1 < d) { \ lp= *i11; d= d1; \ } \ d1= *f12 + ddyz; \ if (d1 < d) { \ lp= *i12; d= d1; \ } \ d1= *f10 + ddxz; \ if (d1 < d) { \ lp= *i10; d= d1; \ } \ d1= fp10 + ddz; \ if (d1 < d) { \ lp= p10; d= d1; \ } \ d1= fq10 + ddxz; \ if (d1 < d) { \ lp= q10; d= d1; \ } \ if (d < *f00) { \ *i00= lp; *f00= d; \ } #define INIP(dely,delz,delzy,delx) \ i00= j0; p00= *i00; \ i01= j0 + (dely); p01= *i01; q01= p01; i01+= delx; \ i10= j0 + (delz); p10= *i10; q10= p10; i10+= delx; \ i11= j0 + (delz) + (dely); \ i12= j0 + (delz) + (delzy); \ f00= q; fp00= *f00; \ f01= q + (dely); fp01= *f01; fq01= fp01; f01+= delx; \ f10= q + (delz); fp10= *f10; fq10= fp10; f10+= delx; \ f11= q + (delz) + (dely); \ f12= q + (delz) + (delzy); #define INCP \ p00= *i00; i00++; \ q01= p01; p01= *i01; i01++; \ q10= p10; p10= *i10; i10++; \ i11++; i12++; \ fp00= *f00; f00++; \ fq01= fp01; fp01= *f01; f01++; \ fq10= fp10; fp10= *f10; f10++; \ f11++; f12++; #define INCP0 \ p00= *i00; i00++; \ q01= p01; p01= *i01; \ q10= p10; p10= *i10; \ i11++; i12++; \ fp00= *f00; f00++; \ fq01= fp01; fp01= *f01; \ fq10= fp10; fp10= *f10; \ f11++; f12++; #define DECP \ p00= *i00; i00--; \ q01= p01; p01= *i01; i01--; \ q10= p10; p10= *i10; i10--; \ i11--; i12--; \ fp00= *f00; f00--; \ fq01= fp01; fp01= *f01; f01--; \ fq10= fp10; fp10= *f10; f10--; \ f11--; f12--; #define DECP0 \ p00= *i00; i00--; \ q01= p01; p01= *i01; \ q10= p10; p10= *i10; \ i11--; i12--; \ fp00= *f00; f00--; \ fq01= fp01; fp01= *f01; \ fq10= fp10; fp10= *f10; \ f11--; f12--; j0= ldt; q= fdt; INIP(0,0,width,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; j0+= width; for (i= 2; i < height; i++) { INIP(-width,0,width,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; j0+= width; } INIP(-width,0,0,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; j0+= width; for (k= 1; k < depth; k++) { INIP(0,-sizeg,width,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; j0+= width; for (i= 2; i < height; i++) { INIP(-width,-sizeg,width,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; j0+= width; } INIP(-width,-sizeg,0,1) for (j= 2; j < width; j++) { TEST INCP } TEST INCP0 TEST q+= width; j0+= width; } j0= ldt + depth * sizeg - 1; q= fdt + depth * sizeg - 1; INIP(0,0,-width,-1) for (j= 2; j < width; j++) { TEST DECP } TEST DECP0 TEST q-= width; j0-= width; for (i= 2; i < height; i++) { INIP(width,0,-width,-1) for (j= 2; j < width; j++) { TEST DECP } TEST DECP0 TEST q-= width; j0-= width; } INIP(width,0,0,-1) for (j= 2; j < width; j++) { TEST DECP } TEST DECP0 TEST q-= width; j0-= width; for (k= 1; k < depth; k++) { INIP(0,sizeg,-width,-1) for (j= 2; j < width; j++) { TEST DECP } TEST DECP0 TEST q-= width; j0-= width; for (i= 2; i < height; i++) { INIP(width,sizeg,-width,-1) for (j= 2; j < width; j++) { TEST DECP } TEST DECP0 TEST q-= width; j0-= width; } INIP(width,sizeg,0,-1) for (j= 2; j < width; j++) { TEST DECP } TEST DECP0 TEST q-= width; j0-= width; } #undef TEST #undef INIP #undef INCP #undef DECP #undef INCP0 #undef DECP0 } template void Lipschitz2D (Image& I, double slope, int dir) { if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); F *p, *r; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t slisize= DimsProd(2, I.dims); float *q= 0, *s; q= new float[slisize]; if (!q) throw Memerr(); ptrdiff_t i, j; for (i= 0, p= I.data; i < numslic; i++, p+= slisize) { if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(s++)= - *(r++); else for (j= 0, r= p, s= q; j < slisize; j++) *(s++)= *(r++); lipschitz_2d_ch(q, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), slope); if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(r++)= - *(s++); else for (j= 0, r= p, s= q; j < slisize; j++) *(r++)= *(s++); } delete[] q; } template void LipschitzRec2D (Image& I, double slope, int dir, con2D conn = con4, recmod rec = rectot) { if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); F *p, *r; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t slisize= DimsProd(2, I.dims); float *q= 0, *s, *t= 0, *u; q= new float[slisize]; t= new float[slisize]; if (!q||!t) throw Memerr(); ptrdiff_t i, j; for (i= 0, p= I.data; i < numslic; i++, p+= slisize) { if (dir) for (j= 0, r= p, s= q, u= t; j < slisize; j++) *(u++)= *(s++)= - *(r++); else for (j= 0, r= p, s= q, u= t; j < slisize; j++) *(u++)= *(s++)= *(r++); lipschitz_2d_ch(q, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), slope); if (conn == con8) reconstruct_gray_2d_8(q, t, I.dims[0], I.dims[1], rec); else reconstruct_gray_2d_4(q, t, I.dims[0], I.dims[1], rec); if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(r++)= - *(s++); else for (j= 0, r= p, s= q; j < slisize; j++) *(r++)= *(s++); } delete[] q; delete[] t; } template void LipschitzTopHat2D (Image& I, double slope, int dir) { if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); F *p, *r; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t slisize= DimsProd(2, I.dims); float *q= 0, *s; F maxF= (std::numeric_limits::is_integer) ?((F)std::numeric_limits::max()):(F)0; q= new float[slisize]; if (!q) throw Memerr(); ptrdiff_t i, j; for (i= 0, p= I.data; i < numslic; i++, p+= slisize) { if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(s++)= - *(r++); else for (j= 0, r= p, s= q; j < slisize; j++) *(s++)= *(r++); lipschitz_2d_ch(q, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), slope); if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(r++)+= maxF + *(s++); else for (j= 0, r= p, s= q; j < slisize; j++) *(r++)-= *(s++); } delete[] q; } template void LipschitzTopHatRec2D (Image& I, double slope, int dir, con2D conn = con4, recmod rec = rectot) { if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); F *p, *r; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t slisize= DimsProd(2, I.dims); float *q= 0, *s, *t= 0, *u; q= new float[slisize]; t= new float[slisize]; F maxF= (std::numeric_limits::is_integer) ?((F)std::numeric_limits::max()):(F)0; if (!q||!t) throw Memerr(); ptrdiff_t i, j; for (i= 0, p= I.data; i < numslic; i++, p+= slisize) { if (dir) for (j= 0, r= p, s= q, u= t; j < slisize; j++) *(u++)= *(s++)= - *(r++); else for (j= 0, r= p, s= q, u= t; j < slisize; j++) *(u++)= *(s++)= *(r++); lipschitz_2d_ch(q, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), slope); if (conn == con8) reconstruct_gray_2d_8(q, t, I.dims[0], I.dims[1], rec); else reconstruct_gray_2d_4(q, t, I.dims[0], I.dims[1], rec); if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(r++)+= maxF + *(s++); else for (j= 0, r= p, s= q; j < slisize; j++) *(r++)-= *(s++); } delete[] q; delete[] t; } template void Lipschitz2D (Image& I, Image*& L, double slope, int dir) { if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!L) L= new Image(I); if (!L) throw Memerr(); L->NewData(); if (!L->data) throw Allocerr(); if (L->nDim != I.nDim) throw Dimserr(); if (!DimsEq(I.nDim,I.dims,L->dims)) throw Sizeerr(); F *p, *r; size_t *t; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t slisize= DimsProd(2, I.dims); float *q, *s; q= new float[slisize]; if (!q) throw Memerr(); ptrdiff_t i, j; for (i= 0, p= I.data, t= L->data; i < numslic; i++, p+= slisize, t+= slisize) { if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(s++)= - *(r++); else for (j= 0, r= p, s= q; j < slisize; j++) *(s++)= *(r++); lipschitz_2d_ch(q, t, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), slope); if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(r++)= - *(s++); else for (j= 0, r= p, s= q; j < slisize; j++) *(r++)= *(s++); } delete[] q; } template void Lipschitz3D (Image& I, double slope, int dir) { if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); F *p, *r; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t slisize= DimsProd(3, I.dims); float *q= 0, *s; q= new float[slisize]; if (!q) throw Memerr(); ptrdiff_t i, j; for (i= 0, p= I.data; i < numslic; i++, p+= slisize) { if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(s++)= - *(r++); else for (j= 0, r= p, s= q; j < slisize; j++) *(s++)= *(r++); lipschitz_3d_ch(q, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), slope); if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(r++)= - *(s++); else for (j= 0, r= p, s= q; j < slisize; j++) *(r++)= *(s++); } delete[] q; } template void LipschitzRec3D (Image& I, double slope, int dir, con3D conn = con18, recmod rec = rectot) { if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); F *p, *r; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t slisize= DimsProd(3, I.dims); float *q= 0, *s, *t= 0, *u; q= new float[slisize]; t= new float[slisize]; if (!q||!t) throw Memerr(); ptrdiff_t i, j; for (i= 0, p= I.data; i < numslic; i++, p+= slisize) { if (dir) for (j= 0, r= p, s= q, u= t; j < slisize; j++) *(u++)= *(s++)= - *(r++); else for (j= 0, r= p, s= q, u= t; j < slisize; j++) *(u++)= *(s++)= *(r++); lipschitz_3d_ch(q, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), slope); if (conn == con18) reconstruct_gray_3d_18(q, t, I.dims[0], I.dims[1], I.dims[2], rec); else reconstruct_gray_3d_6(q, t, I.dims[0], I.dims[1], I.dims[2], rec); if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(r++)= - *(s++); else for (j= 0, r= p, s= q; j < slisize; j++) *(r++)= *(s++); } delete[] q; delete[] t; } template void LipschitzTopHat3D (Image& I, double slope, int dir) { if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); F *p, *r; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t slisize= DimsProd(3, I.dims); float *q, *s; F maxF= (std::numeric_limits::is_integer) ?((F)std::numeric_limits::max()):(F)0; q= new float[slisize]; if (!q) throw Memerr(); ptrdiff_t i, j; for (i= 0, p= I.data; i < numslic; i++, p+= slisize) { if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(s++)= - *(r++); else for (j= 0, r= p, s= q; j < slisize; j++) *(s++)= *(r++); lipschitz_3d_ch(q, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), slope); if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(r++)+= maxF + *(s++); else for (j= 0, r= p, s= q; j < slisize; j++) *(r++)-= *(s++); } delete[] q; } template void LipschitzTopHatRec3D (Image& I, double slope, int dir, con3D conn = con18, recmod rec = rectot) { if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); F *p, *r; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t slisize= DimsProd(3, I.dims); float *q= 0, *s, *t= 0, *u; F maxF= (std::numeric_limits::is_integer) ?((F)std::numeric_limits::max()):(F)0; q= new float[slisize]; t= new float[slisize]; if (!q||!t) throw Memerr(); ptrdiff_t i, j; for (i= 0, p= I.data; i < numslic; i++, p+= slisize) { if (dir) for (j= 0, r= p, s= q, u= t; j < slisize; j++) *(u++)= *(s++)= - *(r++); else for (j= 0, r= p, s= q, u= t; j < slisize; j++) *(u++)= *(s++)= *(r++); lipschitz_3d_ch(q, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), slope); if (conn == con18) reconstruct_gray_3d_18(q, t, I.dims[0], I.dims[1], I.dims[2], rec); else reconstruct_gray_3d_6(q, t, I.dims[0], I.dims[1], I.dims[2], rec); if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(r++)+= maxF + *(s++); else for (j= 0, r= p, s= q; j < slisize; j++) *(r++)-= *(s++); } delete[] q; delete[] t; } template void Lipschitz3D (Image& I, Image*& L, double slope, int dir) { if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!L) L= new Image(I); if (!L) throw Memerr(); L->NewData(); if (!L->data) throw Allocerr(); if (L->nDim != I.nDim) throw Dimserr(); if (!DimsEq(I.nDim,I.dims,L->dims)) throw Sizeerr(); F *p, *r; size_t *t; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t slisize= DimsProd(3, I.dims); float *q= 0, *s; q= new float[slisize]; if (!q) throw Memerr(); ptrdiff_t i, j; for (i= 0, p= I.data, t= L->data; i < numslic; i++, p+= slisize, t+= slisize) { if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(s++)= - *(r++); else for (j= 0, r= p, s= q; j < slisize; j++) *(s++)= *(r++); lipschitz_3d_ch(q, t, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), slope); if (dir) for (j= 0, r= p, s= q; j < slisize; j++) *(r++)= - *(s++); else for (j= 0, r= p, s= q; j < slisize; j++) *(r++)= *(s++); } delete[] q; } //Watershed*************************************************************************************** template class Voxel_WSH { public: Voxel_WSH(ptrdiff_t ix, F& iv) : x(ix), v(iv) {} ptrdiff_t x; F v; }; template inline bool operator<(const Voxel_WSH a1, const Voxel_WSH a2) { return (a1.v > a2.v); } template void watershed_2d(F *dt, G *idt, ptrdiff_t width, ptrdiff_t height, con2D con) { F *i0; G *j0, *j1; ptrdiff_t size = width * height; ptrdiff_t i, j, k; std::priority_queue> buf; #define IND(l,x,y) \ x= l % width; \ y= l / width; i0 = dt; j0 = idt; k = 0; for (i = 0; i < height; i++) { for (j = 0; j < width; j++, i0++, j0++, k++) { if (*j0 && (((j > 0) && !*(j0 - 1)) || ((j < (width - 1)) && !*(j0 + 1)) || ((i > 0) && !*(j0 - width)) || ((i < (height - 1)) && !*(j0 + width)))) { buf.push(Voxel_WSH(k, *i0)); } } } while (!buf.empty()) { k = buf.top().x; buf.pop(); i0 = dt + k; j0 = idt + k; IND(k, j, i) #define PPoint(oper) \ j1= j0 oper; \ if (!*j1) { \ *j1= *j0; \ buf.push(Voxel_WSH(k oper,*(i0 oper))); \ } if (j > 0) { PPoint(-1) } if (j < (width - 1)) { PPoint(+1) } if (i > 0) { PPoint(-width) } if (i < (height - 1)) { PPoint(+width) } if (con > con4) { if (i > 0) { if (j > 0) { PPoint(-1 - width) } if (j < (width - 1)) { PPoint(+1 - width) } } if (i < (height - 1)) { if (j > 0) { PPoint(-1 + width) } if (j < (width - 1)) { PPoint(+1 + width) } } } } #undef PPoint #undef IND } template void watershed_3d(F *dt, G *idt, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, con3D con) { F *i0; G *j0, *j1; ptrdiff_t size = width * height; ptrdiff_t i, j, k, l; std::priority_queue> buf; #define IND(l,x,y,z) \ x= l % width; \ y= (l % size) / width; \ z= l / size; i0 = dt; j0 = idt; l = 0; for (k = 0; k < depth; k++) for (i = 0; i < height; i++) for (j = 0; j < width; j++, i0++, j0++, l++) { if (*j0 && (((j > 0) && !*(j0 - 1)) || ((j < (width - 1)) && !*(j0 + 1)) || ((i > 0) && !*(j0 - width)) || ((i < (height - 1)) && !*(j0 + width)) || ((k > 0) && !*(j0 - size)) || ((k < (depth - 1)) && !*(j0 + size)))) { buf.push(Voxel_WSH(l, *i0)); } } while (!buf.empty()) { l = buf.top().x; buf.pop(); i0 = dt + l; j0 = idt + l; IND(l, j, i, k) #define PPoint(oper) \ j1= j0 oper; \ if (!*j1) { \ *j1= *j0; \ buf.push(Voxel_WSH(l oper,*(i0 oper))); \ } if (j > 0) { PPoint(-1) } if (j < (width - 1)) { PPoint(+1) } if (i > 0) { PPoint(-width) } if (i < (height - 1)) { PPoint(+width) } if (k > 0) { PPoint(-size) } if (k < (depth - 1)) { PPoint(+size) } if (con > con6) { if (k > 0) { if (i > 0) { PPoint(-width - size) } if (i < (height - 1)) { PPoint(+width - size) } if (j > 0) { PPoint(-1 - size) } if (j < (width - 1)) { PPoint(+1 - size) } } if (k < (depth - 1)) { if (i > 0) { PPoint(-width + size) } if (i < (height - 1)) { PPoint(+width + size) } if (j > 0) { PPoint(-1 + size) } if (j < (width - 1)) { PPoint(+1 + size) } } if (i > 0) { if (j > 0) { PPoint(-1 - width) } if (j < (width - 1)) { PPoint(+1 - width) } } if (i < (height - 1)) { if (j > 0) { PPoint(-1 + width) } if (j < (width - 1)) { PPoint(+1 + width) } } if (con > con18) { if (k > 0) { if (i > 0) { if (j > 0) { PPoint(-1 - width - size) } if (j < (width - 1)) { PPoint(+1 - width - size) } } if (i < (height - 1)) { if (j > 0) { PPoint(-1 + width - size) } if (j < (width - 1)) { PPoint(+1 + width - size) } } } if (k < (depth - 1)) { if (i > 0) { if (j > 0) { PPoint(-1 - width + size) } if (j < (width - 1)) { PPoint(+1 - width + size) } } if (i < (height - 1)) { if (j > 0) { PPoint(-1 + width + size) } if (j < (width - 1)) { PPoint(+1 + width + size) } } } } } } #undef PPoint #undef IND } template void Watershed2D(Image& I, Image& J, con2D conn = con4) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 2) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars != 1) || (J.nVars != 1)) throw NVarerr(); if (!DimsEq(I.nDim, I.dims, J.dims)) throw Sizeerr(); ptrdiff_t numslic = DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step = I.dims[0] * I.dims[1]; F* q = I.data; G* p = J.data; ptrdiff_t i; for (i = 0; i < numslic; i++, q += step, p += step) watershed_2d(q, p, I.dims[0], I.dims[1], conn); } template void Watershed3D(Image& I, Image& J, con3D conn = con6) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars != 1) || (J.nVars != 1)) throw NVarerr(); if (!DimsEq(I.nDim, I.dims, J.dims)) throw Sizeerr(); ptrdiff_t numslic = DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step = I.dims[0] * I.dims[1] * I.dims[2]; F* q = I.data; G* p = J.data; ptrdiff_t i; for (i = 0; i < numslic; i++, q += step, p += step) watershed_3d(q, p, I.dims[0], I.dims[1], I.dims[2], conn); } class WshedBuff { size_t BuffBot; size_t *Buffer, *BuffCnt, **pBuffH, **pBuffT; public: WshedBuff(unsigned char *img, size_t size) { unsigned char *p; size_t i, *q; //TODO test Buffer= new size_t[size]; pBuffH= new size_t *[256]; pBuffT= new size_t *[256]; BuffCnt= new size_t[256]; for (i= 0; i < 256; i++) BuffCnt[i]= 0; for (i= 0, p= img; i < size; i++, p++) BuffCnt[*p]++; for (i= 0, q= Buffer; i < 256; i++) { pBuffT[i]= q; pBuffH[i]= q; q+= BuffCnt[i]; } for (i= 0; i < 256; i++) BuffCnt[i]= 0; BuffBot= 256; } ~WshedBuff() { delete[] Buffer; delete[] pBuffH; delete[] pBuffT; delete[] BuffCnt; } void PushPoint(size_t x, unsigned char k) { *((pBuffH[k])++)= x; BuffCnt[k]++; if (k < BuffBot) BuffBot= k; } size_t PopPoint() { size_t x= *(pBuffT[BuffBot]++); (BuffCnt[BuffBot])--; while((BuffBot < 256)&&(BuffCnt[BuffBot] == 0)) BuffBot++; return x; } bool BuffNotEmpty() { return BuffBot < 256; } }; template void watershed_2d(unsigned char *dt, G *idt, ptrdiff_t width, ptrdiff_t height, con2D con) { unsigned char *i0; G *j0, *j1; ptrdiff_t size= width * height; ptrdiff_t i, j, k; WshedBuff buf(dt, size); #define IND(l,x,y) \ x= l % width; \ y= l / width; i0= dt; j0= idt; k= 0; for (i= 0; i < height; i++) { for (j= 0; j < width; j++, i0++, j0++, k++) { if (*j0 && (((j > 0) && !*(j0 - 1)) || ((j < (width - 1)) && !*(j0 + 1)) || ((i > 0) && !*(j0 - width)) || ((i < (height - 1)) && !*(j0 + width)))) { buf.PushPoint(k,*i0); } } } while (buf.BuffNotEmpty()) { k= buf.PopPoint(); i0= dt + k; j0= idt + k; IND(k,j,i) #define PPoint(oper) \ j1= j0 oper; \ if (!*j1) { \ *j1= *j0; \ buf.PushPoint(k oper,*(i0 oper)); \ } if (j > 0) { PPoint(- 1) } if (j < (width - 1)) { PPoint(+ 1) } if (i > 0) { PPoint(- width) } if (i < (height - 1)) { PPoint(+ width) } if (con > con4) { if (i > 0) { if (j > 0) { PPoint(- 1 - width) } if (j < (width - 1)) { PPoint(+ 1 - width) } } if (i < (height - 1)) { if (j > 0) { PPoint(- 1 + width) } if (j < (width - 1)) { PPoint(+ 1 + width) } } } } #undef PPoint #undef IND } template void watershed_3d(unsigned char *dt, G *idt, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, con3D con) { unsigned char *i0; G *j0, *j1; ptrdiff_t size= width * height; ptrdiff_t i, j, k, l; WshedBuff buf(dt, size * depth); #define IND(l,x,y,z) \ x= l % width; \ y= (l % size) / width; \ z= l / size; i0= dt; j0= idt; l= 0; for (k= 0; k < depth; k++) for (i= 0; i < height; i++) for (j= 0; j < width; j++, i0++, j0++, l++) { if (*j0 && (((j > 0) && !*(j0 - 1)) || ((j < (width - 1)) && !*(j0 + 1)) || ((i > 0) && !*(j0 - width)) || ((i < (height - 1)) && !*(j0 + width)) || ((k > 0) && !*(j0 - size)) || ((k < (depth - 1)) && !*(j0 + size)))) { buf.PushPoint(l,*i0); } } while (buf.BuffNotEmpty()) { l= buf.PopPoint(); i0= dt + l; j0= idt + l; IND(l,j,i,k) #define PPoint(oper) \ j1= j0 oper; \ if (!*j1) { \ *j1= *j0; \ buf.PushPoint(l oper,*(i0 oper)); \ } if (j > 0) { PPoint(- 1) } if (j < (width - 1)) { PPoint(+ 1) } if (i > 0) { PPoint(- width) } if (i < (height - 1)) { PPoint(+ width) } if (k > 0) { PPoint(- size) } if (k < (depth - 1)) { PPoint(+ size) } if (con > con6) { if (k > 0) { if (i > 0) { PPoint(- width - size) } if (i < (height - 1)) { PPoint(+ width - size) } if (j > 0) { PPoint(- 1 - size) } if (j < (width - 1)) { PPoint(+ 1 - size) } } if (k < (depth - 1)) { if (i > 0) { PPoint(- width + size) } if (i < (height - 1)) { PPoint(+ width + size) } if (j > 0) { PPoint(- 1 + size) } if (j < (width - 1)) { PPoint(+ 1 + size) } } if (i > 0) { if (j > 0) { PPoint(- 1 - width) } if (j < (width - 1)) { PPoint(+ 1 - width) } } if (i < (height - 1)) { if (j > 0) { PPoint(- 1 + width) } if (j < (width - 1)) { PPoint(+ 1 + width) } } if (con > con18) { if (k > 0) { if (i > 0) { if (j > 0) { PPoint(- 1 - width - size) } if (j < (width - 1)) { PPoint(+ 1 - width - size) } } if (i < (height - 1)) { if (j > 0) { PPoint(- 1 + width - size) } if (j < (width - 1)) { PPoint(+ 1 + width - size) } } } if (k < (depth - 1)) { if (i > 0) { if (j > 0) { PPoint(- 1 - width + size) } if (j < (width - 1)) { PPoint(+ 1 - width + size) } } if (i < (height - 1)) { if (j > 0) { PPoint(- 1 + width + size) } if (j < (width - 1)) { PPoint(+ 1 + width + size) } } } } } } #undef PPoint #undef IND } template void Watershed2D(Image& I, Image& J, con2D conn = con4) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 2) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; unsigned char* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step) watershed_2d(q, p, I.dims[0], I.dims[1], conn); } template void Watershed3D(Image& I, Image& J, con3D conn = con6) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim) ) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; unsigned char* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step) watershed_3d(q, p, I.dims[0], I.dims[1], I.dims[2], conn); } //Distance transform***************************************************************************** struct Vert { double x, v, stp; }; template void distance_nd_1(float* data, ptrdiff_t* dims, int ndim, int dim, double dx, struct Vert* stack, double maxd2) { ptrdiff_t top, i, j, k; double xarg, varg, x, stparg; #define SETST \ stparg= (0.5 * (stack[top].x + xarg + (varg - stack[top].v) / (xarg - stack[top].x))); #define STORE(a, b) \ xarg= a; varg= b; \ if (top >= 0) SETST \ while ((top >= 0) && (stparg <= stack[top].stp)) { \ top--; \ if (top >= 0) SETST \ } \ top++; \ stack[top].stp= (top > 0)?stparg:0.0; \ stack[top].x= xarg; \ stack[top].v= varg; ptrdiff_t nData= DimsProdEx(ndim, dims, dim); ptrdiff_t nInter = DimsProd(dim, dims); ptrdiff_t nLine= dims[dim]; ptrdiff_t nStep = nInter * (nLine - 1); float *p, *q; double d2x2= 0.5 * dx; for(i= 0, q= data; i < nData; i+= nInter) { for(j= 0; j < nInter; j++) { x= 0.0; top= -1; p= q++; for(k= 0; k < nLine ; k++, p+= nInter, x+= dx) if (*p < maxd2) { STORE(x,*p) } p-= nInter; x-= dx; if (top >= 0) { while (k > 0) { while ((top > 0)&&(stack[top].stp > x)) top--; *p= stack[top].v + SQR(stack[top].x - x); k--; p-= nInter; x-= dx; } } } q += nStep; } } #undef SETST #undef STORE template void DistanceData (Binary& I, Image& O, const int dimensionality, bool dosqrt= true) { if ((!I.data)||(!O.data)) throw Allocerr(); if ((dimensionality > I.nDim) || (O.nDim != I.nDim)) throw Dimserr(); if (O.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,O.dims)) throw Sizeerr(); O.SetData(); ptrdiff_t maxdim= DimsMax(dimensionality, I.dims); struct Vert *stack= new struct Vert[maxdim]; if (!stack) throw Memerr(); ptrdiff_t numslic= DimsProd(I.nDim - dimensionality, I.dims + dimensionality); ptrdiff_t slisize= DimsProd(dimensionality, I.dims); float *p, *q; float maxf = SQR(I.Diagonal()); Combine(O, I, maxf); ptrdiff_t i, j; for (i= 0, p= O.data; i < numslic; i++, p+= slisize) { for(j= 0; j < dimensionality; j++) distance_nd_1(p,I.dims,dimensionality,j,I.Dx(j),stack,maxf); if (dosqrt) for (j= 0, q= p; j < slisize; j++, q++) *q= sqrt(*q); } delete[] stack; } template Image* Distance (Binary& I, const int dimensionality, bool dosqrt= true) { if (!I.data) throw Allocerr(); if (dimensionality > I.nDim) throw Dimserr(); Image *O= new Image(I); O->NewData(); if (!O->data) throw Memerr(); DistanceData(I,*O,dimensionality,dosqrt); return O; } template void DistancePower (Image& IO, const int dimensionality, bool dosqrt= true) { if (!IO.data) throw Allocerr(); if (dimensionality > IO.nDim) throw Dimserr(); ptrdiff_t maxdim= DimsMax(dimensionality, IO.dims); struct Vert *stack= new struct Vert[maxdim]; if (!stack) throw Memerr(); ptrdiff_t numslic= DimsProd(IO.nDim - dimensionality, IO.dims + dimensionality); ptrdiff_t slisize= DimsProd(dimensionality, IO.dims); float *p, *q; float maxf = IO.GetMax() + SQR(IO.Diagonal()); ptrdiff_t i, j; for (i= 0, p= IO.data; i < numslic; i++, p+= slisize) { for(j= 0; j < dimensionality; j++) distance_nd_1(p,IO.dims,dimensionality,j,IO.Dx(j),stack,maxf); if (dosqrt) for (j= 0, q= p; j < slisize; j++, q++) *q= sqrt(*q); } delete[] stack; } template struct Vertl { double x, v, stp; F l; }; template void distance_ndl_1(float* data, F* lab, ptrdiff_t* dims, int ndim, int dim, double dx, struct Vertl* stack, double maxd2) { ptrdiff_t top, i, j, k; double xarg, varg, x, stparg; F larg; #define SETST \ stparg= (0.5 * (stack[top].x + xarg + (varg - stack[top].v) / (xarg - stack[top].x))); #define STORE(a, b, c) \ xarg= a; varg= b; larg= c; \ if (top >= 0) SETST \ while ((top >= 0) && (stparg <= stack[top].stp)) { \ top--; \ if (top >= 0) SETST \ } \ top++; \ stack[top].stp= (top > 0)?stparg:0.0; \ stack[top].x= xarg; \ stack[top].v= varg; \ stack[top].l= larg; ptrdiff_t nData= DimsProdEx(ndim, dims, dim); ptrdiff_t nInter = DimsProd(dim, dims); ptrdiff_t nLine= dims[dim]; ptrdiff_t nStep = nInter * (nLine - 1); float *p; F *q; for(i= 0; i < nData; i+= nInter) { for(j= 0; j < nInter; j++) { x= 0.0; top= -1; p= data++; q= lab++; for(k= 0; k < nLine ; k++, p+= nInter, q+= nInter, x+= dx) if (*p < maxd2) { STORE(x,*p,*q) } p-= nInter; q-= nInter; x-= dx; if (top >= 0) { while (k > 0) { while ((top > 0)&&(stack[top].stp > x)) top--; *p= stack[top].v + SQR(stack[top].x - x); *q= stack[top].l; k--; p-= nInter; q-= nInter; x-= dx; } } } data += nStep; lab += nStep; } } #undef SETST #undef STORE template void Mosaic (Image& I, const int dimensionality) { if (!I.data) throw Allocerr(); if (dimensionality > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); Img O(I); O.SetData(); ptrdiff_t maxdim= DimsMax(dimensionality, I.dims); struct Vertl *stack= new struct Vertl[maxdim]; if (!stack) throw Memerr(); ptrdiff_t numslic= DimsProd(I.nDim - dimensionality, I.dims + dimensionality); ptrdiff_t slisize= DimsProd(dimensionality, I.dims); float *p; F *r; float maxf = I.GetMax() + SQR(I.Diagonal()); Bin J(I); Threshold(I, J, 0); J.SetData(IL_BU_NOT); Combine(O, J, maxf); ptrdiff_t i, j; for (i= 0, p= O.data, r= I.data; i < numslic; i++, p+= slisize, r+= slisize) { for(j= 0; j < dimensionality; j++) distance_ndl_1(p,r,I.dims,dimensionality,j,I.Dx(j),stack,maxf); } delete[] stack; } template void DistanceMosaic (Image& I, Image& O, const int dimensionality, const int mode= 0) { if (!I.data || !O.data) throw Allocerr(); if (O.nDim != I.nDim) throw Dimserr(); if ((I.nVars!=1)||(O.nVars!=1)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,O.dims)) throw Sizeerr(); if (!mode) O.SetData(); ptrdiff_t maxdim= DimsMax(dimensionality, I.dims); struct Vertl *stack= new struct Vertl[maxdim]; if (!stack) throw Memerr(); ptrdiff_t numslic= DimsProd(I.nDim - dimensionality, I.dims + dimensionality); ptrdiff_t slisize= DimsProd(dimensionality, I.dims); float *p; F *r; float maxf= SQR(I.Diagonal()); Bin J(I); Threshold(I, J, 0); J.SetData(IL_BU_NOT); Combine(O, J, maxf); ptrdiff_t i, j; for (i= 0, p= O.data, r= I.data; i < numslic; i++, p+= slisize, r+= slisize) { for(j= 0; j < dimensionality; j++) distance_ndl_1(p,r,I.dims,dimensionality,j,I.Dx(j),stack,maxf); } delete[] stack; } template void DistanceMosaicPower (Image& L, Image& IO, const int dimensionality, bool dosqrt= true) { if (!L.data || !IO.data) throw Allocerr(); if (IO.nDim != L.nDim) throw Dimserr(); if ((L.nVars!=1)||(IO.nVars!=1)) throw NVarerr(); if (!DimsEq(L.nDim,L.dims,IO.dims)) throw Sizeerr(); if (dimensionality > IO.nDim) throw Dimserr(); ptrdiff_t maxdim= DimsMax(dimensionality, IO.dims); struct Vertl *stack= new struct Vertl[maxdim]; if (!stack) throw Memerr(); ptrdiff_t numslic= DimsProd(IO.nDim - dimensionality, IO.dims + dimensionality); ptrdiff_t slisize= DimsProd(dimensionality, IO.dims); float *p, *q; float maxf = IO.GetMax() + SQR(IO.Diagonal()); F *r; ptrdiff_t i, j; for (i= 0, p= IO.data, r= L.data; i < numslic; i++, p+= slisize, r+= slisize) { for(j= 0; j < dimensionality; j++) distance_ndl_1(p,r,L.dims,dimensionality,j,L.Dx(j),stack,maxf); // distance_nd_1(p,IO.dims,dimensionality,j,IO.Dx(j),stack,maxf); if (dosqrt) for (j= 0, q= p; j < slisize; j++, q++) *q= sqrt(*q); } delete[] stack; } //Labeling & objects measurement******************************************************* #define SWEEP_BIN \ x132= x32; p1= p; x1= x; \ c1= (size_t)(k-1)+k; \ do { \ k>>= 1; x++; \ if(k == 0) { \ k= LB; x32++; p++; \ while((x32 < ints) && (*p == AB)) \ { x32++; p++; x+= Numb; }; \ } \ } \ while((x32 < ints) && (k & *p) && (x < width)); \ x2= x - 1; \ if (x2 >= width) x2= width - 1; \ x232= x2 / Numb; \ k= LB >> (x2 % Numb); \ c2= (size_t)(-k); template void labelobj1d(size_t *image, ptrdiff_t width, ptrdiff_t x, F* outimage, F val) { ptrdiff_t x32; size_t c1, c2, k; ptrdiff_t x132, x232, x1, x2, ints; size_t *p, *p1; F *q; ints= (width + Numb - 1) / Numb; x32= x / Numb; p= image + x32; k= LB >> (x % Numb); if (*p & k) { SWEEP_BIN p= p1; if(x132 == x232) *p&= ~(c1 & c2); else { *(p++)&= ~c1; for(x32= x132 + 1; x32 < x232; x32++) *(p++)= 0; *(p++)&= ~c2; } if (outimage) { q= outimage + x1; for (i= x1; i <= x2; i++) *(q++)= val; } } } template int measobj1dbin(size_t *image, ptrdiff_t width, ptrdiff_t x, double& num) { ptrdiff_t x32; size_t c1, c2, k; ptrdiff_t x132, x232, x1, x2, ints; size_t *p, *p1; num= 0.0; ints= (width + Numb - 1) / Numb; x32= x / Numb; p= image + x32; k= LB >> (x % Numb); if (*p & k) { SWEEP_BIN p= p1; if(x132 == x232) *p&= ~(c1 & c2); else { *(p++)&= ~c1; for(x32= x132 + 1; x32 < x232; x32++) *(p++)= 0; *(p++)&= ~c2; } num+= x2 - x1 + 1; return 1; } return 0; } template int measobj1dbin(size_t *image, ptrdiff_t width, ptrdiff_t x, double& num, double &mx) { ptrdiff_t x32; size_t c1, c2, k; ptrdiff_t x132, x232, x1, x2, ints; size_t *p, *p1; num= 0.0; ints= (width + Numb - 1) / Numb; x32= x / Numb; p= image + x32; k= LB >> (x % Numb); if (*p & k) { SWEEP_BIN p= p1; if(x132 == x232) *p&= ~(c1 & c2); else { *(p++)&= ~c1; for(x32= x132 + 1; x32 < x232; x32++) *(p++)= 0; *(p++)&= ~c2; } num= x2 - x1 + 1; mx= .5 * (x2 + x1); return 1; } return 0; } #undef SWEEP_BIN #define SWEEP_BIN \ x132= x32; k1= k; p1= p; x1= x; \ do { \ k>>= 1; x++; \ if(k == 0) { \ k= LB; \ do { x32++; p++; x+= Numb; } \ while((x32 < ints) && (*p == AB)); \ x-= Numb; \ } \ } \ while((x32 < ints) && (k & *p) && (x < width)); \ flag= (x == width); \ if(!flag) { x4= x; x432= x32; k4= k; p4= p; } \ if((x32 == ints)||(k == LB)) { c2= AB; k= RB; p--; x32--; } \ else { \ k<<= 1; c2= k; kp= k; \ while(kp != LB) { kp<<= 1; c2|= kp; } \ } \ if(flag) { x4= x - 1; x432= x32; k4= k; p4= p; } \ x2= x - 1; x232= x32; k2= k; p2= p; \ x32= x132; k= k1; p= p1; x= x1; \ do { \ x--; \ if(k == LB) { \ k= RB; \ do { x32--; p--; x-= Numb; } \ while((x32 >= 0) && (*p == AB)); \ x+= Numb; \ } \ else { k<<= 1; } \ } \ while((x32 >= 0) && (k & *p)); \ flag= (x32 < 0); \ if(!flag) { x3= x; x332= x32; k3= k; } \ if(flag||(k == RB)) { c1= AB; k= LB; p++; x32++; } \ else { \ k>>= 1; c1= k; kp= k; \ while(kp != RB) { kp>>= 1; c1|= kp; } \ } \ if(flag) { x3= x + 1; x332= x32; k3= k; } \ x1= x + 1; x132= x32; k1= k; p1= p; #define TESTLINE(xini, kini, pini, inter, xend, kend, newy, newx) \ x= newx; \ x32= xini; \ k= kini; \ p= pini + inter; \ flag= false; \ do { \ equal= !(k & *p); \ if(!flag && !equal) { \ stck.Push(newy, x); \ flag= true; \ } \ else \ if(flag && equal) flag= false; \ if (!(endloop= (x32 == xend) && (k == kend))){ \ x--; \ if(k == LB) { \ k= RB; \ do { \ x32--; \ p--; \ x-= Numb; \ } \ while((x32 != xend) && \ (!flag || (*p == AB)) && \ (flag || !(*p))); \ x+= Numb; \ } \ else k<<= 1; \ } \ } \ while(!endloop); #define TESTLINES2D \ if(conn == con4) { \ if(y < (height-1)) { \ TESTLINE(x232, k2, p2, ints, x132, k1, y + 1, x2) \ } \ if(y > 0) { \ TESTLINE(x232, k2, p2, -ints, x132, k1, y - 1, x2) \ } \ } \ else { \ if(y < (height-1)) { \ TESTLINE(x432, k4, p4, ints, x332, k3, y + 1, x4) \ } \ if(y > 0) { \ TESTLINE(x432, k4, p4, -ints, x332, k3, y - 1, x4) \ } \ } template void labelobj2d(size_t *image, ptrdiff_t width, ptrdiff_t height, ptrdiff_t x, ptrdiff_t y, F* outimage, F val, con2D conn) { ptrdiff_t equal, flag, x32; size_t c1, c2, k1, k2, k3, k4, kp, k, endloop; ptrdiff_t x132, x232, x332, x432, x1, x2, x3, x4, ints; size_t *p, *p1, *p2, *p4; F *q; ptrdiff_t i; Stack2UInt stck; ints= (width + Numb - 1) / Numb; x32= x / Numb; p= image + (y * ints + x32); k= LB >> (x % Numb); if(!(k & *p)) return; stck.Push(y, x); while(stck.Pop(y, x)) { k= LB >> (x % Numb); x32= x / Numb; p= image + (y * ints + x32); if (*p & k) { SWEEP_BIN TESTLINES2D p= p1; if(x132 == x232) *p&= ~(c1 & c2); else { *(p++)&= ~c1; for(x32= x132 + 1; x32 < x232; x32++) *(p++)= 0; *(p++)&= ~c2; } if (outimage) { q= outimage + (y * width + x1); for (i= x1; i <= x2; i++) *(q++)= val; } } } } template int measobj2dbin(size_t *image, ptrdiff_t width, ptrdiff_t height, ptrdiff_t x, ptrdiff_t y, con2D conn, double& num) { ptrdiff_t equal, flag, x32; size_t c1, c2, k1, k2, k3, k4, kp, k, endloop; ptrdiff_t x132, x232, x332, x432, x1, x2, x3, x4, ints; size_t *p, *p1, *p2, *p4; ptrdiff_t i; Stack2UInt stck; num= 0.0; ints= (width + Numb - 1) / Numb; x32= x / Numb; p= image + (y * ints + x32); k= LB >> (x % Numb); if(!(k & *p)) return 0; stck.Push(y, x); while(stck.Pop(y, x)) { k= LB >> (x % Numb); x32= x / Numb; p= image + (y * ints + x32); if (*p & k) { SWEEP_BIN TESTLINES2D p= p1; if(x132 == x232) *p&= ~(c1 & c2); else { *(p++)&= ~c1; for(x32= x132 + 1; x32 < x232; x32++) *(p++)= 0; *(p++)&= ~c2; } num+= x2 - x1 + 1; } } return 1; } template int measobj2dbin(size_t *image, ptrdiff_t width, ptrdiff_t height, ptrdiff_t x, ptrdiff_t y, con2D conn, double& num, double &mx, double &my) { ptrdiff_t equal, flag, x32; size_t c1, c2, k1, k2, k3, k4, kp, k, endloop; ptrdiff_t x132, x232, x332, x432, x1, x2, x3, x4, ints; size_t *p, *p1, *p2, *p4; double qx, sx, sy; ptrdiff_t nx; Stack2UInt stck; num= 0.0; sx= 0.0; sy= 0.0; ints= (width + Numb - 1) / Numb; x32= x / Numb; p= image + (y * ints + x32); k= LB >> (x % Numb); if(!(k & *p)) return 0; stck.Push(y, x); while(stck.Pop(y, x)) { k= LB >> (x % Numb); x32= x / Numb; p= image + (y * ints + x32); if (*p & k) { SWEEP_BIN TESTLINES2D p= p1; if(x132 == x232) *p&= ~(c1 & c2); else { *(p++)&= ~c1; for(x32= x132 + 1; x32 < x232; x32++) *(p++)= 0; *(p++)&= ~c2; } nx= x2 - x1 + 1; qx= 0.5 * (x2 + x1); sx+= (double) nx * qx; sy+= (double) nx * y; num+= nx; } } mx= sx / num; my= sy / num; return 1; } class Edge2D_OA { public: Edge2D_OA(ptrdiff_t ix, ptrdiff_t iy, ptrdiff_t iv) : x(ix) , y(iy), v(iv) {} ptrdiff_t x, y, v; }; inline bool operator<(const Edge2D_OA a1, const Edge2D_OA a2) { return (a1.v < a2.v); } template void open_area2D(F *image, size_t *bin, size_t *buf, ptrdiff_t width, ptrdiff_t height, ptrdiff_t x, ptrdiff_t y, ptrdiff_t objsize, F& endval, con2D conn) { ptrdiff_t equal, flag, x32; size_t c1, c2, k1, k2, k3, k4, kp, k, endloop; ptrdiff_t x132, x232, x332, x432, x1, x2, x3, x4, ints; size_t *p, *p1, *p2, *p4, *r; ptrdiff_t numpix= 0; Stack2UInt stck; std::priority_queue pque; F val, value; //okopirovat objekt, projit okoli value= *(image + (y * width + x)); ints= (width + Numb - 1) / Numb; x32= x / Numb; p= bin + (y * ints + x32); k= LB >> (x % Numb); if(!(k & *p)) return; stck.Push(y, x); while(stck.Pop(y, x)) { k= LB >> (x % Numb); x32= x / Numb; p= bin + (y * ints + x32); if (*p & k) { SWEEP_BIN TESTLINES2D #define PUSHQUE(X,Y) \ pque.push(Edge2D_OA(X,Y,*(image + ((Y) * width + X)))); #define PUSHQUEV(X,Y,V) \ pque.push(Edge2D_OA(X,Y,V)); #define POPQUE(X,Y,V) \ X= pque.top().x; \ Y= pque.top().y; \ V= pque.top().v; \ pque.pop(); #define PUSHLINE(xini, kini, xend, newy, newx, lastx) \ p= bin + ((newy) * ints + xini); \ r= buf + ((newy) * ints + xini); \ k= kini; \ x= newx; \ x32= xini; \ while (x32 <= xend) { \ if((*p|*r)!=AB) { \ do { \ if(!(k & (*p|*r))) { \ PUSHQUE(x, newy) \ } \ x++; \ k>>= 1; \ } while(k && (x <= lastx)); \ } \ x32++; \ k= LB; \ x= Numb * x32; \ p++; r++; \ } if (x4 > x2) PUSHQUE(x4, y); if (x3 < x1) PUSHQUE(x3, y); if(conn == con4) { if(y < (height-1)) { PUSHLINE(x132, k1, x232, y + 1, x1, x2) } if(y > 0) { PUSHLINE(x132, k1, x232, y - 1, x1, x2) } } else { if(y < (height-1)) { PUSHLINE(x332, k3, x432, y + 1, x3, x4) } if(y > 0) { PUSHLINE(x332, k3, x432, y - 1, x3, x4) } } #undef PUSHLINE p= p1; if(x132 == x232) *p&= ~(c1 & c2); else { *(p++)&= ~c1; for(x32= x132 + 1; x32 < x232; x32++) *(p++)= 0; *(p++)&= ~c2; } p= buf + y * ints + x132; if(x132 == x232) *p|= (c1 & c2); else { *(p++)|= c1; for(x32= x132 + 1; x32 < x232; x32++) *(p++)= AB; *(p++)|= c2; } numpix+= x2 - x1 + 1; } } #define TEST(newx,newy) \ k= LB >> ((newx) % Numb); \ x32= (newx) / Numb; \ p= buf + ((newy) * ints + x32); \ if (!(k & *p)) { \ val= *(image + ((newy) * width + newx)); \ if (val > endval) break; \ PUSHQUEV(newx,newy,val); \ } endval= value; while (!pque.empty()) { POPQUE(x,y,val); x32= x / Numb; p= buf + (y * ints + x32); k= LB >> (x % Numb); if (!(k & *p)) { numpix++; endval= val; if (numpix > objsize) break; else { *(image + ((y) * width + x))=0; *p|= k; if (y < (height - 1)) { TEST(x, y+1) } if (x < (width - 1)) { TEST(x+1, y) } if (x > 0) { TEST(x-1, y) } if (y > 0) { TEST(x, y-1) } if (conn == con8) { if (x < (width - 1)) { if (y < (height - 1)) { TEST(x+1, y+1) } if (y > 0) { TEST(x+1, y-1) } } if (x > 0) { if (y < (height - 1)) { TEST(x-1, y+1) } if (y > 0) { TEST(x-1, y-1) } } } } } } } #undef TEST #undef PUSHQUE #undef PUSHQUEV #undef POPQUE #undef TESTLINE #undef TESTLINES2D #define TESTLINE(xini, kini, pini, inter, xend, kend, newz, newy, newx) \ x= newx; \ x32= xini; \ k= kini; \ p= pini + inter; \ flag= false; \ do { \ equal= !(k & *p); \ if(!flag && !equal) { \ que.Push(newz, newy, x); \ flag= true; \ } \ else \ if(flag && equal) flag= false; \ if (!(endloop= (x32 == xend) && (k == kend))){ \ x--; \ if(k == LB) { \ k= RB; \ do { \ x32--; \ p--; \ x-= Numb; \ } \ while((x32 != xend) && \ (!flag || (*p == AB)) && \ (flag || !(*p))); \ x+= Numb; \ } \ else k<<= 1; \ } \ } \ while(!endloop); #define TESTLINES3D \ if(conn == con6) { \ if(y < (height - 1)) { \ TESTLINE(x232, k2, p2, ints, x132, k1, z, y + 1, x2) \ } \ if(y > 0) { \ TESTLINE(x232, k2, p2, -ints, x132, k1, z, y - 1, x2) \ } \ if(z < (depth - 1)) { \ TESTLINE(x232, k2, p2, size, x132, k1, z + 1, y, x2) \ } \ if(z > 0) { \ TESTLINE(x232, k2, p2, -size, x132, k1, z - 1, y, x2) \ } \ } \ else { \ if(y < (height - 1)) { \ TESTLINE(x432, k4, p4, ints, x332, k3, z, y + 1, x4) \ } \ if(y > 0) { \ TESTLINE(x432, k4, p4, -ints, x332, k3, z, y - 1, x4) \ } \ if(z < (depth - 1)) { \ TESTLINE(x432, k4, p4, size, x332, k3, z + 1, y, x4) \ } \ if(z > 0) { \ TESTLINE(x432, k4, p4, -size, x332, k3, z - 1, y, x4) \ } \ if(conn == con26) { \ if(y < (height - 1)) { \ if(z < (depth - 1)) { \ TESTLINE(x432, k4, p4, size + ints, x332, k3, z + 1, y + 1, x4) \ } \ if(z > 0) { \ TESTLINE(x432, k4, p4, -size + ints, x332, k3, z - 1, y + 1, x4) \ } \ } \ if(y > 0) { \ if(z < (depth - 1)) { \ TESTLINE(x432, k4, p4, size - ints, x332, k3, z + 1, y - 1, x4) \ } \ if(z > 0) { \ TESTLINE(x432, k4, p4, -size - ints, x332, k3, z - 1, y - 1, x4) \ } \ } \ } \ else { \ if(y < (height - 1)) { \ if(z < (depth - 1)) { \ TESTLINE(x232, k2, p2, size + ints, x132, k1, z + 1, y + 1, x2) \ } \ if(z > 0) { \ TESTLINE(x232, k2, p2, -size + ints, x132, k1, z - 1, y + 1, x2) \ } \ } \ if(y > 0) { \ if(z < (depth - 1)) { \ TESTLINE(x232, k2, p2, size - ints, x132, k1, z + 1, y - 1, x2) \ } \ if(z > 0) { \ TESTLINE(x232, k2, p2, -size - ints, x132, k1, z - 1, y - 1, x2) \ } \ } \ } \ } template void labelobj3d(size_t *image, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, ptrdiff_t x, ptrdiff_t y, ptrdiff_t z, F* outimage, F val, con3D conn) { ptrdiff_t equal, flag, x32; size_t c1, c2, k1, k2, k3, k4, kp, k, endloop; ptrdiff_t x132, x232, x332, x432, x1, x2, x3, x4, ints, size, bsize; size_t *p, *p1, *p2, *p4; F *q; ptrdiff_t i; Queue3UInt que; ints= (width + Numb - 1) / Numb; size= ints * height; bsize= width * height; x32= x / Numb; p= image + (z * size + y * ints + x32); k= LB >> (x % Numb); if(!(k & *p)) return; que.Push(z, y, x); while(que.Pop(z, y, x)) { k= LB >> (x % Numb); x32= x / Numb; p= image + (z * size + y * ints + x32); if (*p & k) { SWEEP_BIN TESTLINES3D p= p1; if(x132 == x232) *p&= ~(c1 & c2); else { *(p++)&= ~c1; for(x32= x132 + 1; x32 < x232; x32++) *(p++)= 0; *(p++)&= ~c2; } if (outimage) { q= outimage + (z * bsize + y * width + x1); for (i= x1; i <= x2; i++) *(q++)= val; } } } } template int measobj3dbin(size_t *image, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, ptrdiff_t x, ptrdiff_t y, ptrdiff_t z, F* outimage, F val, con3D conn, double& num, double &mx, double &my, double &mz) { ptrdiff_t equal, flag, x32; size_t c1, c2, k1, k2, k3, k4, kp, k, endloop, nx; ptrdiff_t x132, x232, x332, x432, x1, x2, x3, x4, ints, size, bsize; size_t *p, *p1, *p2, *p4; double qx, sx, sy, sz; F *q; Queue3UInt que; num= 0.0; sx= 0.0; sy= 0.0; sz= 0.0; ints= (width + Numb - 1) / Numb; size= ints * height; bsize= width * height; x32= x / Numb; p= image + (z * size + y * ints + x32); k= LB >> (x % Numb); if(!(k & *p)) return 0; que.Push(z, y, x); while(que.Pop(z, y, x)) { k= LB >> (x % Numb); x32= x / Numb; p= image + (z * size + y * ints + x32); if (*p & k) { SWEEP_BIN TESTLINES3D p= p1; if(x132 == x232) *p&= ~(c1 & c2); else { *(p++)&= ~c1; for(x32= x132 + 1; x32 < x232; x32++) *(p++)= 0; *(p++)&= ~c2; } if (outimage) { q= outimage + (z * bsize + y * width + x1); ptrdiff_t i; for (i= x1; i <= x2; i++) *(q++)= val; } nx= x2 - x1 + 1; qx= 0.5 * (x2 + x1); sx+= (double) nx * qx; sy+= (double) nx * y; sz+= (double) nx * z; num+= nx; } } mx= sx / num; my= sy / num; mz= sz / num; return 1; } class Edge3D_OA { public: Edge3D_OA(ptrdiff_t ix, ptrdiff_t iy, ptrdiff_t iz, ptrdiff_t iv) : x(ix) , y(iy), z(iz), v(iv) {} ptrdiff_t x, y, z, v; }; inline bool operator<(const Edge3D_OA a1, const Edge3D_OA a2) { return (a1.v < a2.v); } template void open_volume3D(F *image, size_t *bin, size_t *buf, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, ptrdiff_t x, ptrdiff_t y, ptrdiff_t z, ptrdiff_t objsize, F& endval, con3D conn) { ptrdiff_t equal, flag, x32; size_t c1, c2, k1, k2, k3, k4, kp, k, endloop; ptrdiff_t x132, x232, x332, x432, x1, x2, x3, x4, ints, size, bsize; size_t *p, *p1, *p2, *p4, *r; ptrdiff_t numpix= 0; Queue3UInt que; std::priority_queue pque; F val, value; //okopirovat objekt, projit okoli value= *(image + (y * width + x)); ints= (width + Numb - 1) / Numb; size= ints * height; bsize= width * height; x32= x / Numb; p= bin + (z * size + y * ints + x32); k= LB >> (x % Numb); if(!(k & *p)) return; que.Push(z, y, x); while(que.Pop(z, y, x)) { k= LB >> (x % Numb); x32= x / Numb; p= bin + (z * size + y * ints + x32); if (*p & k) { SWEEP_BIN TESTLINES3D #define PUSHQUE(X,Y,Z) \ pque.push(Edge3D_OA(X,Y,Z,*(image + ((Z) * bsize + (Y) * width + X)))); #define PUSHQUEV(X,Y,Z,V) \ pque.push(Edge3D_OA(X,Y,Z,V)); #define POPQUE(X,Y,Z,V) \ X= pque.top().x; \ Y= pque.top().y; \ Z= pque.top().z; \ V= pque.top().v; \ pque.pop(); #define PUSHLINE(xini, kini, xend, newz, newy, newx, lastx) \ p= bin + ((newz) * size + (newy) * ints + xini); \ r= buf + ((newz) * size + (newy) * ints + xini); \ k= kini; \ x= newx; \ x32= xini; \ while (x32 <= xend) { \ if((*p|*r)!=AB) { \ do { \ if(!(k & (*p|*r))) { \ PUSHQUE(x, newy, newz) \ } \ x++; \ k>>= 1; \ } while(k && (x <= lastx)); \ } \ x32++; \ k= LB; \ x= Numb * x32; \ p++; r++; \ } if (x4 > x2) PUSHQUE(x4, y, z); if (x3 < x1) PUSHQUE(x3, y, z); if(conn == con6) { if(y < (height - 1)) { PUSHLINE(x132, k1, x232, z, y + 1, x1, x2) } if(y > 0) { PUSHLINE(x132, k1, x232, z, y - 1, x1, x2) } if(z < (depth - 1)) { PUSHLINE(x132, k1, x232, z + 1, y, x1, x2) } if(z > 0) { PUSHLINE(x132, k1, x232, z - 1, y, x1, x2) } } else { if(y < (height - 1)) { PUSHLINE(x332, k3, x432, z, y + 1, x3, x4) } if(y > 0) { PUSHLINE(x332, k3, x432, z, y - 1, x3, x4) } if(z < (depth - 1)) { PUSHLINE(x332, k3, x432, z + 1, y, x3, x4) } if(z > 0) { PUSHLINE(x332, k3, x432, z - 1, y, x3, x4) } if(conn == con26) { if(y < (height - 1)) { if(z < (depth - 1)) { PUSHLINE(x332, k3, x432, z + 1, y + 1, x3, x4) } if(z > 0) { PUSHLINE(x332, k3, x432, z - 1, y + 1, x3, x4) } } if(y > 0) { if(z < (depth - 1)) { PUSHLINE(x332, k3, x432, z + 1, y - 1, x3, x4) } if(z > 0) { PUSHLINE(x332, k3, x432, z - 1, y - 1, x3, x4) } } } else { if(y < (height - 1)) { if(z < (depth - 1)) { PUSHLINE(x132, k1, x232, z + 1, y + 1, x1, x2) } if(z > 0) { PUSHLINE(x132, k1, x232, z - 1, y + 1, x1, x2) } } if(y > 0) { if(z < (depth - 1)) { PUSHLINE(x132, k1, x232, z + 1, y - 1, x1, x2) } if(z > 0) { PUSHLINE(x132, k1, x232, z - 1, y - 1, x1, x2) } } } } #undef PUSHLINE p= p1; if(x132 == x232) *p&= ~(c1 & c2); else { *(p++)&= ~c1; for(x32= x132 + 1; x32 < x232; x32++) *(p++)= 0; *(p++)&= ~c2; } p= buf + z * size + y * ints + x132; if(x132 == x232) *p|= (c1 & c2); else { *(p++)|= c1; for(x32= x132 + 1; x32 < x232; x32++) *(p++)= AB; *(p++)|= c2; } numpix+= x2 - x1 + 1; } } #define TEST(newx,newy,newz) \ k= LB >> ((newx) % Numb); \ x32= (newx) / Numb; \ p= buf + ((newz) * size + (newy) * ints + x32); \ if (!(k & *p)) { \ val= *(image + ((newz) * bsize + (newy) * width + newx)); \ if (val > endval) break; \ PUSHQUEV(newx,newy,newz,val); \ } endval= value; while (!pque.empty()) { POPQUE(x,y,z,val); x32= x / Numb; p= buf + (z * size + y * ints + x32); k= LB >> (x % Numb); if (!(k & *p)) { numpix++; endval= val; if (numpix > objsize) break; else { endval= val; *p|= k; if (x > 0) { TEST(x - 1, y, z) } if (x < (width - 1)) { TEST(x + 1, y, z) } if (y > 0) { TEST(x, y - 1, z) } if (y < (height - 1)) { TEST(x, y + 1, z) } if (z > 0) { TEST(x, y, z - 1) } if (z < (depth - 1)) { TEST(x, y, z + 1) } if (conn > con6) { if (z > 0) { if (y > 0) { TEST(x, y - 1, z - 1) } if (y < (height - 1)) { TEST(x, y + 1, z - 1) } if (x > 0) { TEST(x - 1, y, z - 1) } if (x < (width - 1)) { TEST(x + 1, y, z - 1) } } if (z < (depth - 1)) { if (y > 0) { TEST(x, y - 1, z + 1) } if (y < (height - 1)) { TEST(x, y + 1, z + 1) } if (x > 0) { TEST(x - 1, y, z + 1) } if (x < (width - 1)) { TEST(x + 1, y, z + 1) } } if (y > 0) { if (x > 0) { TEST(x - 1, y - 1, z) } if (x < (width - 1)) { TEST(x + 1, y - 1, z) } } if (y < (height - 1)) { if (x > 0) { TEST(x - 1, y + 1, z) } if (x < (width - 1)) { TEST(x + 1, y + 1, z) } } if (conn > con18) { if (z > 0) { if (y > 0) { if (x > 0) { TEST(x - 1, y - 1, z - 1) } if (x < (width - 1)) { TEST(x + 1, y - 1, z - 1) } } if (y < (height - 1)) { if (x > 0) { TEST(x - 1, y + 1, z - 1) } if (x < (width - 1)) { TEST(x + 1, y + 1, z - 1) } } } if (z < (depth - 1)) { if (y > 0) { if (x > 0) { TEST(x - 1, y - 1, z + 1) } if (x < (width - 1)) { TEST(x + 1, y - 1, z + 1) } } if (y < (height - 1)) { if (x > 0) { TEST(x - 1, y + 1, z + 1) } if (x < (width - 1)) { TEST(x + 1, y + 1, z + 1) } } } } } } } } } #undef TEST #undef PUSHQUE #undef PUSHQUEV #undef POPQUE #undef TESTLINE #undef TESTLINES3D #undef SWEEP_BIN #define SWEEP \ p1= p; x1= x; \ do { p++; x++; } \ while((*p == val) && (x < width)); \ x6= x; p4= p - 1; x4= x - 1; \ if(x == width) { p2= p - 1; x2= x - 1; } \ else { p2= p; x2= x; } \ p= p1; x= x1; \ do { x--; p--; } \ while((*p == val) && (x >= 0)); \ x5= x; p3= p + 1; x3= x + 1; \ if(x < 0) { p1= p + 1; x1= x + 1; } \ else { p1= p; x1= x; } template int measobj2d(F* image, F* origim, G* grayim, ptrdiff_t width, ptrdiff_t height, ptrdiff_t x, ptrdiff_t y, double& num, double& nhor, double& nver, double& ndia, double& sx, double& sy, double& sg, double& sgx, double& sgy, double& ming, double& maxg) { ptrdiff_t equal, flag, endloop; ptrdiff_t x1, x2, x3, x4, x5, x6; F val, *p, *p1, *p2, *p3, *p4; double px, qx, np; Stack2UInt stck; G *pg; sx= 0.0; sy= 0.0; num= 0.0; nhor= 0.0; nver= 0.0; ndia= 0.0; sg= 0.0; sgx= 0.0; sgy= 0.0; ming= 1e32; maxg= -1e32; p= image + (y * width + x); if(!*p) return 0; val= *p; stck.Push(y, x); while(stck.Pop(y, x)) { p= image + (y * width + x); if (*p) { SWEEP #define TESTLINE(inter, newy) \ x= x1; \ p= p1 + inter; \ flag= false; \ do { \ equal= (*p != val); \ if(!flag && !equal) { \ stck.Push(newy, x); \ flag= true; \ } \ else \ if(flag && equal) flag= false; \ endloop= (x == x2); \ x++; \ p++; \ } \ while(!endloop); #define calline(yps) \ p= origim + ((yps) * width + x5); \ if ((x5 >= 0)&&(*p != val)) ndia+= 1.0; \ p++; \ if (*p != val) ndia-= 1.0; \ for (x= x3, np= 0.0; x <= x4; x++, p++) if (*p != val) np+= 1.0; \ p--; \ if (*p != val) ndia-= 1.0; \ p++; \ if ((x6 < width)&&(*p != val)) ndia+= 1.0; \ nver+= np; \ ndia+= 2.0 * np; if (x5 >= 0) nhor++; if (x6 < width) nhor++; if(y < (height-1)) { TESTLINE(width, y + 1) calline(y + 1) } if(y > 0) { TESTLINE(-width, y - 1) calline(y - 1) } #undef TESTLINE #undef calline p= p3; for(x= x3; x <= x4; x++) *(p++)= 0; px= x4 - x3 + 1; qx= 0.5 * (x3 + x4); sx+= px * qx; sy+= y * px; num+= px; if (grayim) { pg= grayim + (y * width + x3); for(x= x3, px= 0.0, qx= 0.0; x <= x4; x++, pg++) { px+= *pg; qx+= *pg * x; if (*pg > maxg) maxg= *pg; if (*pg < ming) ming= *pg; } sg+= px; sgx+= qx; sgy+= y * px; } } } return 1; } template int labelobj2d(F* image, ptrdiff_t width, ptrdiff_t height, ptrdiff_t x, ptrdiff_t y, F newval) { ptrdiff_t equal, flag, endloop; ptrdiff_t x1, x2, x3, x4, x5, x6; F val, *p, *p1, *p2, *p3, *p4; Stack2UInt stck; p= image + (y * width + x); if(!*p) return 0; val= *p; stck.Push(y, x); while(stck.Pop(y, x)) { p= image + (y * width + x); if (*p==val) { SWEEP #define TESTLINE(inter, newy) \ x= x1; \ p= p1 + inter; \ flag= false; \ do { \ equal= (*p != val); \ if(!flag && !equal) { \ stck.Push(newy, x); \ flag= true; \ } \ else \ if(flag && equal) flag= false; \ endloop= (x == x2); \ x++; \ p++; \ } \ while(!endloop); if(y < (height-1)) { TESTLINE(width, y + 1) } if(y > 0) { TESTLINE(-width, y - 1) } #undef TESTLINE p= p3; for(x= x3; x <= x4; x++) *(p++)= newval; } } return 1; } //TODO: textural + length + Euler? template int measobj3d(F* image, F* origim, G* grayim, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, ptrdiff_t x, ptrdiff_t y, ptrdiff_t z, double& nvox, double& nx, double& ny, double& nz, double& nxy, double& nxz, double& nyz, double& nxyz, double& sumx, double& sumy, double& sumz, double& sg, double& sgx, double& sgy, double& sgz, double& ming, double& maxg) { ptrdiff_t equal, flag, endloop, size; ptrdiff_t x1, x2, x3, x4, x5, x6; F val, *p, *p1, *p2, *p3, *p4; double px, qx, np; Queue3UInt que; G *pg; sumx= 0.0; sumy= 0.0; sumz= 0.0; sg= 0.0; sgx= 0.0; sgy= 0.0; sgz= 0.0; nvox= 0.0; nx= 0.0; ny= 0.0; nz= 0.0; nxy= 0.0; nxz= 0.0; nyz= 0.0; nxyz= 0.0; ming= 1e32; maxg= -1e32; size= width * height; p= image + (z * size + y * width + x); if(!*p) return 0; val= *p; que.Push(z, y, x); while(que.Pop(z, y, x)) { p= image + (z * size + y * width + x); if (*p) { SWEEP #define TESTLINE(inter, newy, newz) \ x= x1; \ p= p1 + inter; \ flag= false; \ do { \ equal= (*p != val); \ if(!flag && !equal) { \ que.Push(newz, newy, x); \ flag= true; \ } \ else \ if(flag && equal) flag= false; \ endloop= (x == x2); \ x++; \ p++; \ } \ while(!endloop); if(y < (height - 1)) { TESTLINE(width, y + 1, z) } if(y > 0) { TESTLINE(- width, y - 1, z) } if(z < (depth - 1)) { TESTLINE(size, y, z + 1) } if(z > 0) { TESTLINE(- size, y, z - 1) } if(y < (height - 1)) { if(z < (depth - 1)) { TESTLINE(size + width, y + 1, z + 1) } if(z > 0) { TESTLINE(- size + width, y + 1, z - 1) } } if(y > 0) { if(z < (depth - 1)) { TESTLINE(size - width, y - 1, z + 1) } if(z > 0) { TESTLINE(- size - width, y - 1, z - 1) } } #undef TESTLINE #define calline(yps,zet,nver,ndia) \ p= origim + ((zet) * size + (yps) * width + x5); \ if ((x5 >= 0)&&(*p != val)) ndia+= 1; \ p++; \ if (*p != val) ndia-= 1; \ for (x= x3, np= 0; x <= x4; x++, p++) if (*p != val) np+= 1; \ p--; \ if (*p != val) ndia-= 1; \ p++; \ if ((x6 < width)&&(*p != val)) ndia+= 1; \ nver+= np; \ ndia+= 2 * np; if (x5 >= 0) nx++; if (x6 < width) nx++; if(y < (height - 1)) { calline(y + 1, z, ny, nxy) if(z > 0) { calline(y + 1, z - 1, nyz, nxyz) } if(z < (depth - 1)) { calline(y + 1, z + 1, nyz, nxyz) } } if(y > 0) { calline(y - 1, z, ny, nxy) if(z > 0) { calline(y - 1, z - 1, nyz, nxyz) } if(z < (depth - 1)) { calline(y - 1, z + 1, nyz, nxyz) } } if(z > 0) { calline(y, z - 1, nz, nxz) } if(z < (depth - 1)) { calline(y, z + 1, nz, nxz) } #undef calline p= p3; for(x= x3; x <= x4; x++) *(p++)= 0; px= x4 - x3 + 1; qx= 0.5 * (x3 + x4); sumx+= px * qx; sumy+= y * px; sumz+= z * px; nvox+= px; if (grayim) { pg= grayim + (z * size + y * width + x3); for(x= x3, px= 0.0, qx= 0.0; x <= x4; x++, pg++) { px+= *pg; qx+= *pg * x; if (*pg > maxg) maxg= *pg; if (*pg < ming) ming= *pg; } sg+= px; sgx+= qx; sgy+= y * px; sgz+= z * px; } } } return 1; } template int labelobj3d(F* image, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, ptrdiff_t x, ptrdiff_t y, ptrdiff_t z, F newval) { ptrdiff_t equal, flag, endloop, size; ptrdiff_t x1, x2, x3, x4, x5, x6; F val, *p, *p1, *p2, *p3, *p4; Queue3UInt que; size= width * height; p= image + (z * size + y * width + x); if(!*p) return 0; val= *p; que.Push(z, y, x); while(que.Pop(z, y, x)) { p= image + (z * size + y * width + x); if (*p==val) { SWEEP #define TESTLINE(inter, newy, newz) \ x= x1; \ p= p1 + inter; \ flag= false; \ do { \ equal= (*p != val); \ if(!flag && !equal) { \ que.Push(newz, newy, x); \ flag= true; \ } \ else \ if(flag && equal) flag= false; \ endloop= (x == x2); \ x++; \ p++; \ } \ while(!endloop); if(y < (height - 1)) { TESTLINE(width, y + 1, z) } if(y > 0) { TESTLINE(- width, y - 1, z) } if(z < (depth - 1)) { TESTLINE(size, y, z + 1) } if(z > 0) { TESTLINE(- size, y, z - 1) } if(y < (height - 1)) { if(z < (depth - 1)) { TESTLINE(size + width, y + 1, z + 1) } if(z > 0) { TESTLINE(- size + width, y + 1, z - 1) } } if(y > 0) { if(z < (depth - 1)) { TESTLINE(size - width, y - 1, z + 1) } if(z > 0) { TESTLINE(- size - width, y - 1, z - 1) } } #undef TESTLINE p= p3; for(x= x3; x <= x4; x++) *(p++)= newval; } } return 1; } #undef SWEEP template void MeasureObjects1DBin(Binary& I, ObjectArray& O) { if (!I.data) throw Allocerr(); if (!I.nDim) throw Dimserr(); ptrdiff_t ints= ((I.dims[0] + Numb - 1) / Numb); ptrdiff_t width= I.dims[0]; ptrdiff_t step= ints; size_t *pdat= new size_t[step]; if (!pdat) throw Memerr(); memcpy(pdat, I.data, step * sizeof(size_t)); double dx= I.Dx(0); size_t *p= pdat; size_t k; ptrdiff_t i, j; double mx; Object po(3); double n; for(i= 0; i < ints; i++, p++) if(*p) { k= LB; j= Numb * i; do { if(k & *p) { if (!measobj1dbin(pdat, width, j, n, mx)) { delete [] pdat; throw Imgerr(); } po[0]= I.bounds[0] + dx * j; //first point x po[1]= I.bounds[0] + dx * mx; po[2]= dx * n; //length O.push_back(po); } j++; k>>= 1; } while(k&&(j < width)); } delete [] pdat; } template void Label2D(Binary& image, Image& I, con2D conn, F& val) { size_t *q, *p, k; ptrdiff_t i, j, m, width, ints, height, numslic, ssize, l; F *outd, *r, *s, *t; if (!image.data || !I.data) throw Allocerr(); if ((image.nDim < 2) || (image.nDim != I.nDim)) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,image.dims)) throw Sizeerr(); outd= I.data; ints= ((image.dims[0] + Numb - 1) / Numb); width= image.dims[0]; height= image.dims[1]; ssize= width * height; numslic= DimsProd(image.nDim - 2, image.dims + 2); Bin pimage(image); pimage.SetData(image.data); q= pimage.data; for (l= 0, t= outd; l < numslic; l++, t+= ssize) { p= q; for(m= 0, s= t ; m < height; m++, s+= width) for(i= 0; i < ints; i++, p++) if(*p) { k= LB; j= Numb * i; r= s + j; do { if(k & *p) { if (conn) labelobj2d(q, width, height, j, m, t, val, conn); else *r= val; val++; if (!val) throw Valerr(); } j++; r++; k>>= 1; } while(k&&(j < width)); } q+= ints * height; outd+= ssize; } } template void MeasureObjects2DBin(Binary& I, ObjectArray& O, con2D con = con4) { if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); ptrdiff_t ints= ((I.dims[0] + Numb - 1) / Numb); ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; ptrdiff_t step= ints * I.dims[1]; size_t *pdat= new size_t[step]; if (!pdat) throw Memerr(); memcpy(pdat, I.data, step * sizeof(size_t)); double dx= I.Dx(0); double dy= I.Dx(1); size_t *p= pdat; size_t k; ptrdiff_t i, j, m; double mx, my; Object po(5); double n; for(m= 0; m < height; m++) for(i= 0; i < ints; i++, p++) if(*p) { k= LB; j= Numb * i; do { if(k & *p) { if (!measobj2dbin(pdat, width, height, j, m, con, n, mx, my)) { delete [] pdat; throw Imgerr(); } po[0]= I.bounds[0] + dx * j; //first point x po[1]= I.bounds[2] + dy * m; //first point y po[2]= I.bounds[0] + dx * mx; po[3]= I.bounds[2] + dy * my; po[4]= dx * dy * n; //area O.push_back(po); } j++; k>>= 1; } while(k&&(j < width)); } delete [] pdat; } template void Reconstruct1DBin(Binary& I, Binary& J) { if (!I.data || !J.data) throw Allocerr(); if (J.nDim != I.nDim) throw Dimserr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t ints= ((I.dims[0] + Numb - 1) / Numb); ptrdiff_t width= I.dims[0]; ptrdiff_t step= ints; size_t *pdat= new size_t[step]; if (!pdat) throw Memerr(); ptrdiff_t numslic= DimsProd(I.nDim - 1, I.dims + 1); size_t *p, *r; size_t k; ptrdiff_t i, j, m, l; Binary pimg(1,I.dims); Binary qimg(1,J.dims); pimg.data= I.data; qimg.data= J.data; for (l= 0; l < numslic; l++) { memcpy(pdat, qimg.data, step * sizeof(size_t)); p= pdat; r= pimg.data; for(i= 0; i < ints; i++, p++, r++) if(*p & *r) { k= LB; j= Numb * i; do { if(k & *p & *r) labelobj1d(pdat, width, j, 0, 0); j++; k>>= 1; } while(k&&(j < width)); } pimg.SetData(qimg.data); pimg.SetData(IL_BB_DIF, pdat); pimg.data+= step; qimg.data+= step; } delete [] pdat; } template void Reconstruct2DBin(Binary& I, Binary& J, con2D con = con4) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 2) || (J.nDim != I.nDim)) throw Dimserr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t ints= ((I.dims[0] + Numb - 1) / Numb); ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; ptrdiff_t step= ints * I.dims[1]; size_t *pdat= new size_t[step]; if (!pdat) throw Memerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); size_t *p, *r; size_t k; ptrdiff_t i, j, m, l; Binary pimg(2,I.dims); Binary qimg(2,J.dims); pimg.data= I.data; qimg.data= J.data; for (l= 0; l < numslic; l++) { memcpy(pdat, qimg.data, step * sizeof(size_t)); p= pdat; r= pimg.data; for(m= 0; m < height; m++) for(i= 0; i < ints; i++, p++, r++) if(*p & *r) { k= LB; j= Numb * i; do { if(k & *p & *r) labelobj2d(pdat, width, height, j, m, 0, 0, con); j++; k>>= 1; } while(k&&(j < width)); } pimg.SetData(qimg.data); pimg.SetData(IL_BB_DIF, pdat); pimg.data+= step; qimg.data+= step; } delete [] pdat; } template void FillHoles2DBin (Binary& I, con2D con = con4) { if (!I.data) throw Allocerr(); if (I.nDim < 2) throw Dimserr(); ptrdiff_t ints= ((I.dims[0] + Numb - 1) / Numb); ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; ptrdiff_t step= ints * I.dims[1]; Bin pimg(2,I.dims); Binary qimg(2,I.dims); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); size_t *p; size_t k; ptrdiff_t i, j, m, l; qimg.data= I.data; for (l= 0; l < numslic; l++) { pimg.SetData(qimg.data); pimg.SetData(IL_BU_NOT); pimg.EraseEnd(); p= pimg.data; for(i= 0; i < ints; i++, p++) if(*p) { k= LB; j= Numb * i; do { if(k & *p) labelobj2d(pimg.data, width, height, j, 0, 0, 0, con); j++; k>>= 1; } while(k&&(j < width)); } p= pimg.data + ints * (I.dims[1] - 1); for(i= 0; i < ints; i++, p++) if(*p) { k= LB; j= Numb * i; do { if(k & *p) labelobj2d(pimg.data, width, height, j, height - 1, 0, 0, con); j++; k>>= 1; } while(k&&(j < width)); } p= pimg.data; k= LB; for(m= 0; m < height; m++, p+= ints) if(k & *p) labelobj2d(pimg.data, width, height, 0, m, 0, 0, con); p= pimg.data + ints - 1; k= (!(I.dims[0] % Numb))?(RB):(RB << (Numb - (I.dims[0] % Numb))); for(m= 0; m < height; m++, p+= ints) if(k & *p) labelobj2d(pimg.data, width, height, width - 1, m, 0, 0, con); qimg.SetData(IL_BB_OR, pimg.data); qimg.data+= step; } } template void Clean2DBin (Binary& I, int num, con2D con = con4) { Bin J(I); J.SetData(I.data); Erode2DBin(I, num); Reconstruct2DBin(I, J, con); } template void Clean2DBinSize (Binary& I, int num, con2D con = con4, thrmod tmod = thrge) { //only 1 image ObjectArray O; MeasureObjects2DBin(I, O, con); ObjectArray O1; SelectObjects(O, O1, 4, num, tmod); Bin J(I); J.SetData(I.data); I.SetData(IL_BU_SET); // ShiftObjects(O1,0,-0.5*I.Dx(0)); ShiftObjects(O1,1,-0.5*I.Dx(1)); PointsBin(I, O1); Reconstruct2DBin(I, J, con); } template void LabelObjects2D(Image& I, Image& J, bool bconst= false) { if (!I.data||!J.data) throw Allocerr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if ((2 > I.nDim) || (2 > J.nDim)) throw Dimserr(); if (!DimsEq(2,I.dims,J.dims)) throw Sizeerr();; ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; ptrdiff_t step= I.dims[0] * I.dims[1]; J.SetData(I.data); F max= J.GetMax(); F *p= J.data; F val= max+1; ptrdiff_t i, j; for(j= 0; j < height; j++) for(i= 0; i < width; i++, p++) if (*p&&(*p<=max)) { if (!labelobj2d(J.data, width, height, i, j, val)) { throw Imgerr(); } if (!bconst) val++; } } template void MeasureObjects2D(Image& I, ObjectArray& O) { //TODO: orientace if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; ptrdiff_t step= I.dims[0] * I.dims[1]; F *pdat= new F[step]; if (!pdat) throw Memerr(); memcpy(pdat, I.data, step * sizeof(F)); double dx= I.Dx(0); double dy= I.Dx(1); double xycal, wx, wy, wxy; weights2D(dx, dy, &wx, &wxy, &wy); xycal= dx * dy / sqrt( dx * dx + dy * dy); F *p= pdat; ptrdiff_t i, j; Object po(7); double n, nx, ny, nxy, sx, sy, d0, d1, d2, d3, d4; for(j= 0; j < height; j++) for(i= 0; i < width; i++, p++) if (*p) { F lab= *p; if (!measobj2d(pdat, I.data, (size_t *)NULL, width, height, i, j, n, nx, ny, nxy, sx, sy, d0, d1, d2, d3, d4)) { delete [] pdat; throw Imgerr(); } po[0]= I.bounds[0] + dx * i; //first point x po[1]= I.bounds[2] + dy * j; //first point y po[2]= I.bounds[0] + dx * (sx / n); //mass center po[3]= I.bounds[2] + dy * (sy / n); //mass center po[4]= dx * dy * n; //area po[5]= (wx * dy * nx + wy * dx * ny + wxy * xycal * nxy) * M_PI_2; //perimeter po[6]= lab; O.push_back(po); } delete [] pdat; } template void MeasureObjects2D(Image& I, Image& J, ObjectArray& O) { if (!I.data||!J.data) throw Allocerr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if ((2 > I.nDim) || (2 > J.nDim)) throw Dimserr(); if (!DimsEq(2,I.dims,J.dims)) throw Sizeerr();; ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; ptrdiff_t step= I.dims[0] * I.dims[1]; F *pdat= new F[step]; if (!pdat) throw Memerr(); memcpy(pdat, I.data, step * sizeof(F)); double dx= I.Dx(0); double dy= I.Dx(1); double xycal, wx, wy, wxy; weights2D(dx, dy, &wx, &wxy, &wy); xycal= dx * dy / sqrt( dx * dx + dy * dy); F *p= pdat; ptrdiff_t i, j; Object po(12); double n, nx, ny, nxy, sx, sy, sg, sgx, sgy, ming, maxg; for(j= 0; j < height; j++) for(i= 0; i < width; i++, p++) if (*p) { F lab= *p; if (!measobj2d(pdat, I.data, J.data, width, height, i, j, n, nx, ny, nxy, sx, sy, sg, sgx, sgy, ming, maxg)) { delete [] pdat; throw Imgerr(); } po[0]= I.bounds[0] + dx * i; //first point x po[1]= I.bounds[2] + dy * j; //first point y po[2]= I.bounds[0] + dx * (sx / n); //mass center po[3]= I.bounds[2] + dy * (sy / n); //mass center po[4]= dx * dy * n; //area po[5]= (wx * dy * nx + wy * dx * ny + wxy * xycal * nxy) * M_PI_2; //perimeter po[6]= I.bounds[0] + dx * (sgx / sg); //gray mass center po[7]= I.bounds[2] + dy * (sgy / sg); //gray mass center po[8]= sg / n; //average gray po[9]= ming; //minimal gray po[10]= maxg; //maximal gray po[11]= lab; O.push_back(po); } delete [] pdat; } template void MeasureObjects2D(Image& I, F& val, ObjectArray& O) { if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; double dx= I.Dx(0); double dy= I.Dx(1); double xycal, wx, wy, wxy; weights2D(dx, dy, &wx, &wxy, &wy); xycal= dx * dy / sqrt( dx * dx + dy * dy); Object po(7); double *sx, *sy; ptrdiff_t *n, *nx, *ny, *nxy, *ne, *x1, *y1, i, j; F *i0, *i1, p0, p1; #define ALLOCD(x) \ x= new double[val]; \ if (!x) throw Memerr(); \ for (i= 0; i < val; i++) x[i]= 0.0; #define ALLOCI(x) \ x= new ptrdiff_t[val]; \ if (!x) throw Memerr(); \ for (i= 0; i < val; i++) x[i]= 0; ALLOCI(n) ALLOCI(x1) ALLOCI(y1) ALLOCI(nx) ALLOCI(ny) ALLOCI(nxy) ALLOCD(sx) ALLOCD(sy) ALLOCI(ne) #undef ALLOCD #undef ALLOCI #define SINCR(N,A,B) \ if (A != B) { N[A]++; N[B]++; } #define FRST(A,I,J) \ if (!n[A]) { x1[A]= I; y1[A]= J; } i0= i1= I.data; FRST(*i1,0,0) n[*i1]++; p1= *i1; i1++; for (j= 1; j < width; j++) { FRST(*i1,j,0) n[*i1]++; sx[*i1]+= j; SINCR(nx,*i1,p1) p1= *i1; i1++; } for (i= 1; i < height; i++) { FRST(*i1,0,i) n[*i1]++; sy[*i1]+= i; SINCR(ny,*i1,*i0) p1= *i1; i1++; p0= *i0; i0++; for (j= 1; j < width; j++) { FRST(*i1,j,i) n[*i1]++; sx[*i1]+= j; sy[*i1]+= i; SINCR(nx,*i1,p1) SINCR(ny,*i1,*i0) SINCR(nxy,*i0,p1) SINCR(nxy,*i1,p0) if (*i1 != p0) { if ( p1 != p0) ne[p0]++; if (*i0 == p0) ne[p0]--; } if (p1 != *i0) { if (*i1 != *i0) ne[*i0]++; if ( p1 == p0) ne[*i0]--; } p1= *i1; i1++; p0= *i0; i0++; } } #undef SINCR #undef FRST for (i= 1; i < val; i++) { po[0]= I.bounds[0] + dx * x1[i]; //first point x po[1]= I.bounds[2] + dy * y1[i]; //first point y po[2]= I.bounds[0] + dx * (sx[i] / n[i]); //mass center po[3]= I.bounds[2] + dy * (sy[i] / n[i]); //mass center po[4]= dx * dy * n[i]; //area po[5]= (wx * dy * nx[i] + wy * dx * ny[i] + wxy * xycal * nxy[i]) * M_PI_2; //perimeter po[6]= ne[i] / 2; //Euler O.push_back(po); } delete [] n; delete [] x1; delete [] y1; delete [] nx; delete [] ny; delete [] nxy; delete [] sx; delete [] sy; delete [] ne; } template void MeasureObjects2D(Image& I, Image& J, F& val, ObjectArray& O) { if (!I.data||!J.data) throw Allocerr(); if ((2 > I.nDim) || (2 > J.nDim)) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if (!DimsEq(2,I.dims,J.dims)) throw Sizeerr();; ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; double dx= I.Dx(0); double dy= I.Dx(1); double xycal, wx, wy, wxy; weights2D(dx, dy, &wx, &wxy, &wy); xycal= dx * dy / sqrt( dx * dx + dy * dy); Object po(10); double *sx, *sy, *sg, *sgx, *sgy; ptrdiff_t i, j, *n, *x1, *y1, *nx, *ny, *nxy, *ne; F *i0, *i1, p0, p1; G *j0, *j1, q0, q1; #define ALLOCD(x) \ x= new double[val]; \ if (!x) throw Memerr(); \ for (i= 0; i < val; i++) x[i]= 0.0; #define ALLOCI(x) \ x= new ptrdiff_t[val]; \ if (!x) throw Memerr(); \ for (i= 0; i < val; i++) x[i]= 0; ALLOCI(n) ALLOCI(x1) ALLOCI(y1) ALLOCI(nx) ALLOCI(ny) ALLOCI(nxy) ALLOCD(sx) ALLOCD(sy) ALLOCD(sg) ALLOCD(sgx) ALLOCD(sgy) ALLOCI(ne) #undef ALLOCD #undef ALLOCI #define SINCR(N,A,B) \ if (A != B) { N[A]++; N[B]++; } #define FRST(A,I,J) \ if (!n[A]) { x1[A]= I; y1[A]= J; } i0= i1= I.data; j0= j1= J.data; FRST(*i1,0,0) n[*i1]++; sg[*i1]+= *j1; p1= *i1; i1++; q1= *j1; j1++; for (j= 1; j < width; j++) { FRST(*i1,j,0) n[*i1]++; sx[*i1]+= j; sg[*i1]+= *j1; sgx[*i1]+= *j1 * j; SINCR(nx,*i1,p1) p1= *i1; i1++; q1= *j1; j1++; } for (i= 1; i < height; i++) { FRST(*i1,0,i) n[*i1]++; sy[*i1]+= i; sg[*i1]+= *j1; sgy[*i1]+= *j1 * i; SINCR(ny,*i1,*i0) p1= *i1; i1++; p0= *i0; i0++; q1= *j1; j1++; q0= *j0; j0++; for (j= 1; j < width; j++) { FRST(*i1,j,i) n[*i1]++; sx[*i1]+= j; sy[*i1]+= i; sg[*i1]+= *j1; sgx[*i1]+= *j1 * j; sgy[*i1]+= *j1 * i; SINCR(nx,*i1,p1) SINCR(ny,*i1,*i0) SINCR(nxy,*i0,p1) SINCR(nxy,*i1,p0) if (*i1 != p0) { if ( p1 != p0) ne[p0]++; if (*i0 == p0) ne[p0]--; } if (p1 != *i0) { if (*i1 != *i0) ne[*i0]++; if ( p1 == p0) ne[*i0]--; } p1= *i1; i1++; p0= *i0; i0++; q1= *j1; j1++; q0= *j0; j0++; } } #undef SINCR #undef FRST for (i= 1; i < val; i++) { po[0]= I.bounds[0] + dx * x1[i]; //first point x po[1]= I.bounds[2] + dy * y1[i]; //first point y po[2]= I.bounds[0] + dx * (sx[i] / n[i]); //mass center po[3]= I.bounds[2] + dy * (sy[i] / n[i]); //mass center po[4]= dx * dy * n[i]; //area po[5]= (wx * dy * nx[i] + wy * dx * ny[i] + wxy * xycal * nxy[i]) * M_PI_2; //perimeter po[6]= ne[i] / 2; //Euler po[7]= I.bounds[0] + dx * (sgx[i] / sg[i]); //gray mass center po[8]= I.bounds[2] + dy * (sgy[i] / sg[i]); //gray mass center po[9]= sg[i] / n[i]; //average gray O.push_back(po); } delete [] n; delete [] x1; delete [] y1; delete [] nx; delete [] ny; delete [] nxy; delete [] sx; delete [] sy; delete [] sg; delete [] sgx; delete [] sgy; delete [] ne; } template void Label3D(Binary& image, Image& I, con3D conn, F& val) { size_t *q, *p, k; ptrdiff_t i, j, m, o, ints, width, height, depth, numslic, psize, ssize, l; F *outd, *r, *s, *t, *u; if (!image.data || !I.data) throw Allocerr(); if ((image.nDim < 3) || (image.nDim != I.nDim)) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,image.dims)) throw Sizeerr(); outd= I.data; ints= ((image.dims[0] + Numb - 1) / Numb); width= image.dims[0]; height= image.dims[1]; depth= image.dims[2]; numslic= DimsProd(image.nDim - 3, image.dims + 3); psize= width * height; ssize= depth * psize; Bin pimage(image); pimage.SetData(image.data); q= pimage.data; for (l= 0, u= outd; l < numslic; l++, u+= ssize) { p= q; for(o= 0, t= u; o < depth; o++, t+= psize) for(m= 0, s= t; m < height; m++, s+= width) for(i= 0; i < ints; i++, p++) if(*p) { k= LB; j= Numb * i; r= s + j; do { if(k & *p) { if (conn) labelobj3d(q, width, height, depth, j, m, o, u, val, conn); else *r= val; val++; if (!val) throw Valerr(); } j++; r++; k>>= 1; } while(k&&(j < width)); } q+= ints * height * depth; outd+= ssize; } } template void MeasureAndLabelObjects3DBin(Binary& I, Image& J, ObjectArray& O, con3D con, F& val) { if ((!I.data)||(!J.data)) throw Allocerr(); if ((3 > I.nDim)||(3 > J.nDim)) throw Dimserr(); if (J.nVars!=1) throw NVarerr(); if (!DimsEq(3,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t ints= ((I.dims[0] + Numb - 1) / Numb); ptrdiff_t width= I.dims[0]; ptrdiff_t height= I.dims[1]; ptrdiff_t depth= I.dims[2]; ptrdiff_t size= ints * height * depth; size_t *pdat= new size_t[size]; if (!pdat) throw Memerr(); memcpy(pdat, I.data, size * sizeof(size_t)); double dx= I.Dx(0); double dy= I.Dx(1); double dz= I.Dx(2); size_t *p= pdat; size_t k; ptrdiff_t i, j, m, o; double mx, my, mz; Object po(7); double n; for(o= 0; o < depth; o++) for(m= 0; m < height; m++) for(i= 0; i < ints; i++, p++) if(*p) { k= LB; j= Numb * i; do { if(k & *p) { if (!measobj3dbin(pdat, width, height, depth, j, m, o, J.data, val, con, n, mx, my, mz)) { delete [] pdat; throw Imgerr(); } val++; po[0]= I.bounds[0] + dx * j; //first point x po[1]= I.bounds[2] + dy * m; //first point y po[2]= I.bounds[4] + dz * o; //first point z po[3]= I.bounds[0] + dx * mx; po[4]= I.bounds[2] + dy * my; po[5]= I.bounds[4] + dz * mz; po[6]= dx * dy * dz * n; //area O.push_back(po); } j++; k>>= 1; } while(k&&(j < width)); } delete [] pdat; } template void MeasureObjects3DBin(Binary& I, ObjectArray& O, con3D con = con6) { if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); ptrdiff_t ints= ((I.dims[0] + Numb - 1) / Numb); ptrdiff_t width= I.dims[0]; ptrdiff_t height= I.dims[1]; ptrdiff_t depth= I.dims[2]; ptrdiff_t size= ints * height * depth; size_t *pdat= new size_t[size]; if (!pdat) throw Memerr(); memcpy(pdat, I.data, size * sizeof(size_t)); double dx= I.Dx(0); double dy= I.Dx(1); double dz= I.Dx(2); size_t *p= pdat; size_t k; ptrdiff_t i, j, m, o; double mx, my, mz; Object po(7); double n; for(o= 0; o < depth; o++) for(m= 0; m < height; m++) for(i= 0; i < ints; i++, p++) if(*p) { k= LB; j= Numb * i; do { if(k & *p) { if (!measobj3dbin(pdat, width, height, depth, j, m, o, 0, 0, con, n, mx, my, mz)) { delete [] pdat; throw Imgerr(); } po[0]= I.bounds[0] + dx * j; //first point x po[1]= I.bounds[2] + dy * m; //first point y po[2]= I.bounds[4] + dz * o; //first point z po[3]= I.bounds[0] + dx * mx; po[4]= I.bounds[2] + dy * my; po[5]= I.bounds[4] + dz * mz; po[6]= dx * dy * dz * n; //volume O.push_back(po); } j++; k>>= 1; } while(k&&(j < width)); } delete [] pdat; } template void Reconstruct3DBin(Binary& I, Binary& J, con3D con = con6) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim)) throw Dimserr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t ints= ((I.dims[0] + Numb - 1) / Numb); ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; ptrdiff_t depth= I.dims[2]; ptrdiff_t step= ints * height * depth; size_t *pdat= new size_t[step]; if (!pdat) throw Memerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); size_t *p, *r; size_t k; ptrdiff_t i, j, m, l, o; Binary pimg(3,I.dims); Binary qimg(3,J.dims); pimg.data= I.data; qimg.data= J.data; for (l= 0; l < numslic; l++) { memcpy(pdat, qimg.data, step * sizeof(size_t)); p= pdat; r= pimg.data; for(o= 0; o < depth; o++) for(m= 0; m < height; m++) for(i= 0; i < ints; i++, p++, r++) if(*p & *r) { k= LB; j= Numb * i; do { if(k & *p & *r) labelobj3d(pdat, width, height, depth, j, m, o, 0, 0, con); j++; k>>= 1; } while(k&&(j < width)); } pimg.SetData(qimg.data); pimg.SetData(IL_BB_DIF, pdat); pimg.data+= step; qimg.data+= step; } delete [] pdat; } template void FillHoles3DBin (Binary& I, con3D con = con18) { if (!I.data) throw Allocerr(); if (I.nDim < 3) throw Dimserr(); ptrdiff_t ints= ((I.dims[0] + Numb - 1) / Numb); ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; ptrdiff_t depth= I.dims[2]; ptrdiff_t step= ints * height * depth; Bin pimg(3,I.dims); Binary qimg(3,I.dims); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); size_t *p, *r; size_t k; ptrdiff_t i, j, m, l, o; qimg.data= I.data; for (l= 0; l < numslic; l++) { pimg.SetData(qimg.data); pimg.SetData(IL_BU_NOT); pimg.EraseEnd(); p= pimg.data; for(m= 0; m < height; m++) for(i= 0; i < ints; i++, p++) if(*p) { k= LB; j= Numb * i; do { if(k & *p) labelobj3d(pimg.data, width, height, depth, j, m, 0, 0, 0, con); j++; k>>= 1; } while(k&&(j < width)); } p= pimg.data + ints * I.dims[1] * (I.dims[2] - 1); for(m= 0; m < height; m++) for(i= 0; i < ints; i++, p++) if(*p) { k= LB; j= Numb * i; do { if(k & *p) labelobj3d(pimg.data, width, height, depth, j, m, depth - 1, 0, 0, con); j++; k>>= 1; } while(k&&(j < width)); } r= pimg.data; for(o= 0; o < depth; o++, r+= (ints * I.dims[1])) for(i= 0, p= r; i < ints; i++, p++) if(*p) { k= LB; j= Numb * i; do { if(k & *p) labelobj3d(pimg.data, width, height, depth, j, 0, o, 0, 0, con); j++; k>>= 1; } while(k&&(j < width)); } r= pimg.data + ints * (I.dims[1] - 1); for(o= 0; o < depth; o++, r+= (ints * I.dims[1])) for(i= 0, p= r; i < ints; i++, p++) if(*p) { k= LB; j= Numb * i; do { if(k & *p) labelobj3d(pimg.data, width, height, depth, j, height - 1, o, 0, 0, con); j++; k>>= 1; } while(k&&(j < width)); } p= pimg.data; k= LB; for(o= 0; o < depth; o++) for(m= 0; m < height; m++, p+= ints) if(k & *p) labelobj3d(pimg.data, width, height, depth, 0, m, o, 0, 0, con); p= pimg.data + ints - 1; k= (!(I.dims[0] % Numb))?(RB):(RB << (Numb - (I.dims[0] % Numb))); for(o= 0; o < depth; o++) for(m= 0; m < height; m++, p+= ints) if(k & *p) labelobj3d(pimg.data, width, height, depth, width - 1, m, o, 0, 0, con); qimg.SetData(IL_BB_OR, pimg.data); qimg.data+= step; } } template void Clean3DBin (Binary& I, int num, con3D con = con18) { Bin J(I); J.SetData(I.data); Erode3DBin(I, num); Reconstruct3DBin(I, J, con); } template void Clean2D3DBin (Binary& I, int num2, int num3, con3D con = con18) { Bin J(I); J.SetData(I.data); Erode2D3DBin(I, num2, num3); Reconstruct3DBin(I, J, con); } template void Clean3DBinSize (Binary& I, int num, con3D con = con18, thrmod tmod = thrge) { //only 1 image ObjectArray O; MeasureObjects3DBin(I, O, con); ObjectArray O1; SelectObjects(O, O1, 6, num, tmod); Bin J(I); J.SetData(I.data); I.SetData(IL_BU_SET); // ShiftObjects(O1,0,-0.5*I.Dx(0)); ShiftObjects(O1,1,-0.5*I.Dx(1)); ShiftObjects(O1,2,-0.5*I.Dx(2)); PointsBin(I, O1); Reconstruct3DBin(I, J, con); } template void LabelObjects3D(Image& I, Image& J, bool bconst= false) { if (!I.data||!J.data) throw Allocerr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if ((3 > I.nDim) || (3 > J.nDim)) throw Dimserr(); if (!DimsEq(3,I.dims,J.dims)) throw Sizeerr();; ptrdiff_t depth= I.dims[2]; ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F *pdat= new F[step]; memcpy(pdat, I.data, step * sizeof(F)); // J.SetData(I.data); F max= I.GetMax(); F *p= J.data; F val= max+1; ptrdiff_t i, j, k; for(k= 0; k < depth; k++) for(j= 0; j < height; j++) for(i= 0; i < width; i++, p++) if (*p&&(*p<=max)) { if (!labelobj3d(pdat, width, height, depth, i, j, k, val)) { delete [] pdat; throw Imgerr(); } if (!bconst) val++; } memcpy(J.data, pdat, step * sizeof(F)); delete [] pdat; } template void MeasureObjects3D(Image& I, ObjectArray& O) { if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t depth= I.dims[2]; ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F *pdat= new F[step]; memcpy(pdat, I.data, step * sizeof(F)); double dx= I.Dx(0); double dy= I.Dx(1); double dz= I.Dx(2); double sx= dy * dz; double sy= dx * dz; double sz= dx * dy; double sxy= dz * dx * dy / sqrt( dx * dx + dy * dy); double sxz= dz * dx * dy / sqrt( dx * dx + dz * dz); double syz= dz * dx * dy / sqrt( dy * dy + dz * dz); double sxyz= dz * dx * dy / sqrt( dx * dx + dy * dy + dz * dz); double wx, wy, wz, wxy, wxz, wyz, wxyz; weights3D(dx, dy, dz, &wx, &wy, &wz, &wxy, &wxz, &wyz, &wxyz); F *p= pdat; ptrdiff_t i, j, k; Object po(9); double n, nx, ny, nz, nxy, nxz, nyz, nxyz, mx, my, mz, d0, d1, d2, d3, ming, maxg; for(k= 0; k < depth; k++) for(j= 0; j < height; j++) for(i= 0; i < width; i++, p++) if (*p) { F lab= *p; if (!measobj3d(pdat, I.data, (size_t *)NULL, width, height, depth, i, j, k, n, nx, ny, nz, nxy, nxz, nyz, nxyz, mx, my, mz, d0, d1, d2, d3, ming, maxg)) { delete [] pdat; throw Imgerr(); } po[0]= I.bounds[0] + dx * i; ////first point x po[1]= I.bounds[2] + dy * j; ////first point y po[2]= I.bounds[4] + dz * k; ////first point z po[3]= I.bounds[0] + dx * (mx / n); //mass center po[4]= I.bounds[2] + dy * (my / n); //mass center po[5]= I.bounds[4] + dz * (mz / n); //mass center po[6]= dx * dy * dz * n; //volume po[7]= (wx * sx * nx + wy * sy * ny + wz * sz * nz + wxy * sxy * nxy + wxz * sxz * nxz + wyz * syz * nyz + wxyz * sxyz * nxyz) * 2.0; //surface area po[8]= lab; O.push_back(po); } delete [] pdat; } template void MeasureObjects3D(Image& I, Image& J, ObjectArray& O) { if (!I.data||!J.data) throw Allocerr(); if ((3 > I.nDim) || (3 > J.nDim)) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if (!DimsEq(3,I.dims,J.dims)) throw Sizeerr();; ptrdiff_t depth= I.dims[2]; ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F *pdat= new F[step]; memcpy(pdat, I.data, step * sizeof(F)); double dx= I.Dx(0); double dy= I.Dx(1); double dz= I.Dx(2); double sx= dy * dz; double sy= dx * dz; double sz= dx * dy; double sxy= dz * dx * dy / sqrt( dx * dx + dy * dy); double sxz= dz * dx * dy / sqrt( dx * dx + dz * dz); double syz= dz * dx * dy / sqrt( dy * dy + dz * dz); double sxyz= dz * dx * dy / sqrt( dx * dx + dy * dy + dz * dz); double wx, wy, wz, wxy, wxz, wyz, wxyz; weights3D(dx, dy, dz, &wx, &wy, &wz, &wxy, &wxz, &wyz, &wxyz); F *p= pdat; ptrdiff_t i, j, k; Object po(15); double n, nx, ny, nz, nxy, nxz, nyz, nxyz, mx, my, mz, sg, sgx, sgy, sgz, ming, maxg; for(k= 0; k < depth; k++) for(j= 0; j < height; j++) for(i= 0; i < width; i++, p++) if (*p) { F lab= *p; if (!measobj3d(pdat, I.data, J.data, width, height, depth, i, j, k, n, nx, ny, nz, nxy, nxz, nyz, nxyz, mx, my, mz, sg, sgx, sgy, sgz, ming, maxg)) { delete [] pdat; throw Imgerr(); } po[0]= I.bounds[0] + dx * i; //first point x po[1]= I.bounds[2] + dy * j; //first point y po[2]= I.bounds[4] + dz * k; //first point z po[3]= I.bounds[0] + dx * (mx / n); //mass center po[4]= I.bounds[2] + dy * (my / n); //mass center po[5]= I.bounds[4] + dz * (mz / n); //mass center po[6]= dx * dy * dz * n; //volume po[7]= (wx * sx * nx + wy * sy * ny + wz * sz * nz + wxy * sxy * nxy + wxz * sxz * nxz + wyz * syz * nyz + wxyz * sxyz * nxyz) * 2.0; //surface area po[8]= I.bounds[0] + dx * (sgx / sg); //gray mass center po[9]= I.bounds[2] + dy * (sgy / sg); //gray mass center po[10]= I.bounds[4] + dz * (sgz / sg); //gray mass center po[11]= sg / n; //average gray po[12]= ming; //minimal gray po[13]= maxg; //maximal gray po[14]= lab; O.push_back(po); } delete [] pdat; } template void MeasureObjects3D(Image& I, F& val, ObjectArray& O) { if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr();; if (I.nVars!=1) throw NVarerr(); ptrdiff_t depth= I.dims[2]; ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; double dx= I.Dx(0); double dy= I.Dx(1); double dz= I.Dx(2); double ax= dy * dz; double ay= dx * dz; double az= dx * dy; double axy= dz * dx * dy / sqrt( dx * dx + dy * dy); double axz= dz * dx * dy / sqrt( dx * dx + dz * dz); double ayz= dz * dx * dy / sqrt( dy * dy + dz * dz); double axyz= dz * dx * dy / sqrt( dx * dx + dy * dy + dz * dz); double wx, wy, wz, wxy, wxz, wyz, wxyz; weights3D(dx, dy, dz, &wx, &wy, &wz, &wxy, &wxz, &wyz, &wxyz); double bx= dx; double by= dy; double bz= dz; double bxy= dx * dy / sqrt(dx * dx + dy * dy); double bxz= dx * dz / sqrt(dx * dx + dz * dz); double byz= dy * dz / sqrt(dy * dy + dz * dz); double bxyz= dx * dy * dz / sqrt(dx * dx * dy * dy + dy * dy * dz * dz + dx * dx * dz * dz); double vx, vy, vz, vxy, vxz, vyz, vxyz; weights3D(1.0 / dx, 1.0 / dy, 1.0 / dz, &vx, &vy, &vz, &vxy, &vxz, &vyz, &vxyz); ptrdiff_t i, j, k; Object po(9); double *sx, *sy, *sz; ptrdiff_t *n, *x1, *y1, *z1, *nx, *ny, *nz, *nxy, *nxz, *nyz, *nxyz, *nex, *ney, *nez, *nexy, *nexz, *neyz, *nexyz; F *i00, *i10, p00, p10, *i01, *i11, p01, p11; #define ALLOCD(x) \ x= new double[val]; \ if (!x) throw Memerr(); \ for (i= 0; i < val; i++) x[i]= 0.0; #define ALLOCI(x) \ x= new ptrdiff_t[val]; \ if (!x) throw Memerr(); \ for (i= 0; i < val; i++) x[i]= 0; ALLOCI(n) ALLOCI(x1) ALLOCI(y1) ALLOCI(z1) ALLOCI(nx) ALLOCI(ny) ALLOCI(nz) ALLOCI(nxy) ALLOCI(nxz) ALLOCI(nyz) ALLOCI(nxyz) ALLOCI(nex) ALLOCI(ney) ALLOCI(nez) ALLOCI(nexy) ALLOCI(nexz) ALLOCI(neyz) ALLOCI(nexyz) ALLOCD(sx) ALLOCD(sy) ALLOCD(sz) #undef ALLOCD #undef ALLOCI #define SINCR(N,A,B) \ if (A != B) { N[A]++; N[B]++; } #define FRST(A,I,J,K) \ if (!n[A]) { x1[A]= I; y1[A]= J; z1[A]= K; } #define EINCR4(N,A,B,C,D) \ if (D != A) { \ if (C != A) N[A]++; \ if (A == B) N[A]--; \ } \ if (B != C) { \ if (D != B) N[B]++; \ if (A == B) N[B]--; \ } #define EINCR6(N,A,B,C,D,E,F) \ if ((A != B)&&(A != C)) N[A]++; \ if ((D == E)&&(F != D)) N[D]--; i10= i01= i11= I.data; FRST(*i11,0,0,0); n[*i11]++; p11= *i11; i11++; for (j= 1; j < width; j++) { FRST(*i11,j,0,0); n[*i11]++; sx[*i11]+= j; SINCR(nx,*i11,p11) p11= *i11; i11++; } for (i= 1; i < height; i++) { FRST(*i11,0,i,0); n[*i11]++; sy[*i11]+= i; SINCR(ny,*i11,*i01) p11= *i11; i11++; p01= *i01; i01++; for (j= 1; j < width; j++) { FRST(*i11,j,i,0); n[*i11]++; sx[*i11]+= j; sy[*i11]+= i; SINCR(nx,*i11,p11) SINCR(ny,*i11,*i01) SINCR(nxy,*i01,p11) SINCR(nxy,*i11,p01) EINCR4(nez,p01,*i01,p11,*i11) p11= *i11; i11++; p01= *i01; i01++; } } for (k= 1; k < depth; k++) { FRST(*i11,0,0,k); n[*i11]++; sz[*i11]+= k; i01= i11; i00= i10; p11= *i11; i11++; p10= *i10; i10++; for (j= 1; j < width; j++) { FRST(*i11,j,0,k); n[*i11]++; sx[*i11]+= j; sz[*i11]+= k; SINCR(nx,*i11,p11) SINCR(nz,*i11,*i10) SINCR(nxz,*i11,p10) SINCR(nxz,*i10,p11) EINCR4(ney,p11,*i11,p10,*i10) p11= *i11; i11++; p10= *i10; i10++; } for (i= 1; i < height; i++) { FRST(*i11,0,i,k); n[*i11]++; sy[*i11]+= i; sz[*i11]+= k; SINCR(ny,*i11,*i01) SINCR(nz,*i11,*i10) SINCR(nyz,*i11,*i00) SINCR(nyz,*i01,*i10) EINCR4(nex,*i01,*i00,*i11,*i10) p11= *i11; i11++; p01= *i01; i01++; p10= *i10; i10++; p00= *i00; i00++; for (j= 1; j < width; j++) { FRST(*i11,j,i,k); n[*i11]++; sx[*i11]+= j; sy[*i11]+= i; sz[*i11]+= k; SINCR(nx,*i11,p11) SINCR(ny,*i11,*i01) SINCR(nz,*i11,*i10) SINCR(nxy,*i11,p01) SINCR(nxy,*i01,p11) SINCR(nyz,*i11,*i00) SINCR(nyz,*i01,*i10) SINCR(nxz,*i11,p10) SINCR(nxz,*i10,p11) SINCR(nxyz,*i11,p00) SINCR(nxyz,*i00,p11) SINCR(nxyz,*i01,p10) SINCR(nxyz,*i10,p01) EINCR4(nex,*i01,*i00,*i11,*i10) EINCR4(ney,p11,*i11,p10,*i10) EINCR4(nez,p01,*i01,p11,*i11) EINCR4(nexy,*i01,*i00,p11,p10) EINCR4(nexy,p01,p00,*i11,*i10) EINCR4(nexz,*i01,p00,*i11,p10) EINCR4(nexz,p01,*i00,p11,*i10) EINCR4(neyz,p01,*i01,p10,*i10) EINCR4(neyz,p00,*i00,p11,*i11) EINCR6(nexyz,*i00,p10,*i11,p00,*i01,p11) EINCR6(nexyz,p00,p11,*i10,p01,*i00,*i11) EINCR6(nexyz,p01,p10,*i11,p00,*i01,*i10) EINCR6(nexyz,*i01,p11,*i10,p01,*i00,p10) p11= *i11; i11++; p01= *i01; i01++; p10= *i10; i10++; p00= *i00; i00++; } } } #undef SINCR #undef FRST #undef EINCR4 #undef EINCR6 for (i= 1; i < val; i++) { po[0]= I.bounds[0] + dx * x1[i]; //first point x po[1]= I.bounds[2] + dy * y1[i]; //first point y po[2]= I.bounds[4] + dz * z1[i]; //first point z po[3]= I.bounds[0] + dx * (sx[i] / n[i]); //mass center po[4]= I.bounds[2] + dy * (sy[i] / n[i]); //mass center po[5]= I.bounds[4] + dz * (sz[i] / n[i]); //mass center po[6]= dx * dy * dz * n[i]; //volume po[7]= (wx * ax * nx[i] + wy * ay * ny[i] + wz * az * nz[i] + wxy * axy * nxy[i] + wxz * axz * nxz[i] + wyz * ayz * nyz[i] + wxyz * axyz * nxyz[i]) * 2; //surface po[8]= (vx * bx * nex[i] + vy * by * ney[i] + vz * bz * nez[i] + vxy * bxy * nexy[i] + vxz * bxz * nexz[i] + vyz * byz * neyz[i] + 2.0 * vxyz * bxyz * nexyz[i]); //length O.push_back(po); } delete [] n; delete [] x1; delete [] y1; delete [] z1; delete [] nx; delete [] ny; delete [] nz; delete [] nxy; delete [] nxz; delete [] nyz; delete [] nxyz; delete [] nex; delete [] ney; delete [] nez; delete [] nexy; delete [] nexz; delete [] neyz; delete [] nexyz; delete [] sx; delete [] sy; delete [] sz; } template void MeasureObjects3D(Image& I, Image& J, F& val, ObjectArray& O) { if (!I.data||!J.data) throw Allocerr(); if ((3 > I.nDim) || (3 > J.nDim)) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if (!DimsEq(3,I.dims,J.dims)) throw Sizeerr();; ptrdiff_t depth= I.dims[2]; ptrdiff_t height= I.dims[1]; ptrdiff_t width= I.dims[0]; double dx= I.Dx(0); double dy= I.Dx(1); double dz= I.Dx(2); double ax= dy * dz; double ay= dx * dz; double az= dx * dy; double axy= dz * dx * dy / sqrt( dx * dx + dy * dy); double axz= dz * dx * dy / sqrt( dx * dx + dz * dz); double ayz= dz * dx * dy / sqrt( dy * dy + dz * dz); double axyz= dz * dx * dy / sqrt( dx * dx + dy * dy + dz * dz); double wx, wy, wz, wxy, wxz, wyz, wxyz; weights3D(dx, dy, dz, &wx, &wy, &wz, &wxy, &wxz, &wyz, &wxyz); double bx= dx; double by= dy; double bz= dz; double bxy= dx * dy / sqrt(dx * dx + dy * dy); double bxz= dx * dz / sqrt(dx * dx + dz * dz); double byz= dy * dz / sqrt(dy * dy + dz * dz); double bxyz= dx * dy * dz / sqrt(dx * dx * dy * dy + dy * dy * dz * dz + dx * dx * dz * dz); double vx, vy, vz, vxy, vxz, vyz, vxyz; weights3D(1.0 / dx, 1.0 / dy, 1.0 / dz, &vx, &vy, &vz, &vxy, &vxz, &vyz, &vxyz); ptrdiff_t i, j, k; Object po(13); double *sx, *sy, *sz, *sg, *sgx, *sgy, *sgz; ptrdiff_t *n, *x1, *y1, *z1, *nx, *ny, *nz, *nxy, *nxz, *nyz, *nxyz, *nex, *ney, *nez, *nexy, *nexz, *neyz, *nexyz; F *i00, *i10, p00, p10, *i01, *i11, p01, p11; G *j00, *j10, q00, q10, *j01, *j11, q01, q11; #define ALLOCD(x) \ x= new double[val]; \ if (!x) throw Memerr(); \ for (i= 0; i < val; i++) x[i]= 0.0; #define ALLOCI(x) \ x= new ptrdiff_t[val]; \ if (!x) throw Memerr(); \ for (i= 0; i < val; i++) x[i]= 0; ALLOCI(n) ALLOCI(x1) ALLOCI(y1) ALLOCI(z1) ALLOCI(nx) ALLOCI(ny) ALLOCI(nz) ALLOCI(nxy) ALLOCI(nxz) ALLOCI(nyz) ALLOCI(nxyz) ALLOCI(nex) ALLOCI(ney) ALLOCI(nez) ALLOCI(nexy) ALLOCI(nexz) ALLOCI(neyz) ALLOCI(nexyz) ALLOCD(sx) ALLOCD(sy) ALLOCD(sz) ALLOCD(sg) ALLOCD(sgx) ALLOCD(sgy) ALLOCD(sgz) #undef ALLOCD #undef ALLOCI #define SINCR(N,A,B) \ if (A != B) { N[A]++; N[B]++; } #define FRST(A,I,J,K) \ if (!n[A]) { x1[A]= I; y1[A]= J; z1[A]= K; } #define EINCR4(N,A,B,C,D) \ if (D != A) { \ if (C != A) N[A]++; \ if (A == B) N[A]--; \ } \ if (B != C) { \ if (D != B) N[B]++; \ if (A == B) N[B]--; \ } #define EINCR6(N,A,B,C,D,E,F) \ if ((A != B)&&(A != C)) N[A]++; \ if ((D == E)&&(F != D)) N[D]--; i10= i01= i11= I.data; j10= j01= j11= J.data; FRST(*i11,0,0,0) n[*i11]++; sg[*i11]+= *j11; p11= *i11; i11++; q11= *j11; j11++; for (j= 1; j < width; j++) { FRST(*i11,j,0,0) n[*i11]++; sg[*i11]+= *j11; sx[*i11]+= j; sgx[*i11]+= *j11 * j; SINCR(nx,*i11,p11) p11= *i11; i11++; q11= *j11; j11++; } for (i= 1; i < height; i++) { FRST(*i11,0,i,0) n[*i11]++; sg[*i11]+= *j11; sy[*i11]+= i; sgy[*i11]+= *j11 * i; SINCR(ny,*i11,*i01) p11= *i11; i11++; p01= *i01; i01++; q11= *j11; j11++; q01= *j01; j01++; for (j= 1; j < width; j++) { FRST(*i11,j,i,0) n[*i11]++; sg[*i11]+= *j11; sx[*i11]+= j; sgx[*i11]+= *j11 * j; sy[*i11]+= i; sgy[*i11]+= *j11 * i; SINCR(nx,*i11,p11) SINCR(ny,*i11,*i01) SINCR(nxy,*i01,p11) SINCR(nxy,*i11,p01) EINCR4(nez,p01,*i01,p11,*i11) p11= *i11; i11++; p01= *i01; i01++; q11= *j11; j11++; q01= *j01; j01++; } } for (k= 1; k < depth; k ++) { FRST(*i11,0,0,k) n[*i11]++; sg[*i11]+= *j11; sz[*i11]+= k; sgz[*i11]+= *j11 * k; i01= i11; i00= i10; j01= j11; j00= j10; p11= *i11; i11++; p10= *i10; i10++; q11= *j11; j11++; q01= *j01; j01++; for (j= 1; j < width; j++) { FRST(*i11,j,0,k) n[*i11]++; sg[*i11]+= *j11; sx[*i11]+= j; sgx[*i11]+= *j11 * j; sz[*i11]+= k; sgz[*i11]+= *j11 * k; SINCR(nx,*i11,p11) SINCR(nz,*i11,*i10) SINCR(nxz,*i11,p10) SINCR(nxz,*i10,p11) EINCR4(ney,p11,*i11,p10,*i10) p11= *i11; i11++; p10= *i10; i10++; q11= *j11; j11++; q01= *j01; j01++; } for (i= 1; i < height; i++) { FRST(*i11,0,i,k) n[*i11]++; sg[*i11]+= *j11; sy[*i11]+= i; sgy[*i11]+= *j11 * i; sz[*i11]+= k; sgz[*i11]+= *j11 * k; SINCR(ny,*i11,*i01) SINCR(nz,*i11,*i10) SINCR(nyz,*i11,*i00) SINCR(nyz,*i01,*i10) EINCR4(nex,*i01,*i00,*i11,*i10) p11= *i11; i11++; p01= *i01; i01++; p10= *i10; i10++; p00= *i00; i00++; q11= *j11; j11++; q01= *j01; j01++; q10= *j10; j10++; q00= *j00; j00++; for (j= 1; j < width; j++) { FRST(*i11,j,i,k) n[*i11]++; sg[*i11]+= *j11; sx[*i11]+= j; sgx[*i11]+= *j11 * j; sy[*i11]+= i; sgy[*i11]+= *j11 * i; sz[*i11]+= k; sgz[*i11]+= *j11 * k; SINCR(nx,*i11,p11) SINCR(ny,*i11,*i01) SINCR(nz,*i11,*i10) SINCR(nxy,*i11,p01) SINCR(nxy,*i01,p11) SINCR(nyz,*i11,*i00) SINCR(nyz,*i01,*i10) SINCR(nxz,*i11,p10) SINCR(nxz,*i10,p11) SINCR(nxyz,*i11,p00) SINCR(nxyz,*i00,p11) SINCR(nxyz,*i01,p10) SINCR(nxyz,*i10,p01) EINCR4(nex,*i01,*i00,*i11,*i10) EINCR4(ney,p11,*i11,p10,*i10) EINCR4(nez,p01,*i01,p11,*i11) EINCR4(nexy,*i01,*i00,p11,p10) EINCR4(nexy,p01,p00,*i11,*i10) EINCR4(nexz,*i01,p00,*i11,p10) EINCR4(nexz,p01,*i00,p11,*i10) EINCR4(neyz,p01,*i01,p10,*i10) EINCR4(neyz,p00,*i00,p11,*i11) EINCR6(nexyz,*i00,p10,*i11,p00,*i01,p11) EINCR6(nexyz,p00,p11,*i10,p01,*i00,*i11) EINCR6(nexyz,p01,p10,*i11,p00,*i01,*i10) EINCR6(nexyz,*i01,p11,*i10,p01,*i00,p10) p11= *i11; i11++; p01= *i01; i01++; p10= *i10; i10++; p00= *i00; i00++; q11= *j11; j11++; q01= *j01; j01++; q10= *j10; j10++; q00= *j00; j00++; } } } #undef SINCR #undef FRST #undef EINCR4 #undef EINCR6 for (i= 1; i < val; i++) { po[0]= I.bounds[0] + dx * x1[i]; //first point x po[1]= I.bounds[2] + dy * y1[i]; //first point y po[2]= I.bounds[4] + dz * z1[i]; //first point z po[3]= I.bounds[0] + dx * (sx[i] / n[i]); //mass center po[4]= I.bounds[2] + dy * (sy[i] / n[i]); //mass center po[5]= I.bounds[4] + dz * (sz[i] / n[i]); //mass center po[6]= dx * dy * dz * n[i]; //volume po[7]= (wx * ax * nx[i] + wy * ay * ny[i] + wz * az * nz[i] + wxy * axy * nxy[i] + wxz * axz * nxz[i] + wyz * ayz * nyz[i] + wxyz * axyz * nxyz[i]) * 2; //surface po[8]= (vx * bx * nex[i] + vy * by * ney[i] + vz * bz * nez[i] + vxy * bxy * nexy[i] + vxz * bxz * nexz[i] + vyz * byz * neyz[i] + 2.0 * vxyz * bxyz * nexyz[i]); //length po[9]= I.bounds[0] + dx * (sgx[i] / sg[i]); //gray mass center po[10]= I.bounds[2] + dy * (sgy[i] / sg[i]); //gray mass center po[11]= I.bounds[4] + dz * (sgz[i] / sg[i]); //gray mass center po[12]= sg[i] / n[i]; //average gray O.push_back(po); } delete [] n; delete [] x1; delete [] y1; delete [] z1; delete [] nx; delete [] ny; delete [] nz; delete [] nxy; delete [] nxz; delete [] nyz; delete [] nxyz; delete [] nex; delete [] ney; delete [] nez; delete [] nexy; delete [] nexz; delete [] neyz; delete [] nexyz; delete [] sx; delete [] sy; delete [] sz; delete [] sg; delete [] sgx; delete [] sgy; delete [] sgz; } template void labbin2d(F *inL, ptrdiff_t width, ptrdiff_t height, size_t *out, ptrdiff_t cnt) { F *iL0, *iL1, pL0, pL1; ptrdiff_t i, j, n, l, nints, size; size_t k, c, *o; size_t qL[8]; ptrdiff_t numL, dif; nints= (width + Numb - 1) / Numb; size= width * height; #define TEST(L) \ if (L) { \ dif= true; \ for (l= 0; l < numL; l++) \ if (qL[l] == (L)) { \ dif= false; \ break; \ } \ if (dif) { \ if ((numL>0)&&(numL > cnt)) { \ c|= k; \ break; \ } \ else { \ qL[numL]= (L); \ numL+= 1; \ } \ } \ } o= out; iL0= inL; iL1= iL0 + width; for(i= 1; i < height; i++) { pL0= *(iL0++); pL1= *(iL1++); k= LB; c= 0; for(j= 1; j < width; j++) { numL= 0; do { TEST(pL0) TEST(pL1) TEST(*iL0) TEST(*iL1) } while (false); pL0= *(iL0++); pL1= *(iL1++); k>>= 1; if (!k) { k= LB; *(o++)= c; c= 0; } } do { TEST(pL0) TEST(pL1) TEST(pL0) TEST(pL1) } while (false); if (k != LB) *(o++)= c; } iL1= iL0; pL0= *(iL0++); pL1= *(iL1++); k= LB; c= 0; for(j= 1; j < width; j++) { numL= 0; do { TEST(pL0) TEST(pL1) TEST(*iL0) TEST(*iL1) } while (false); pL0= *(iL0++); pL1= *(iL1++); k>>= 1; if (!k) { k= LB; *(o++)= c; c= 0; } } do { TEST(pL0) TEST(pL1) TEST(pL0) TEST(pL1) } while (false); if (k != LB) *(o++)= c; } #undef TEST template void labbin3d(F *inL, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, size_t *out, ptrdiff_t cnt) { F *iL00, *iL01,*iL10, *iL11, pL00, pL01, pL10, pL11; ptrdiff_t i, j, n, l, nints, size, sizeg; size_t k, c, *o; size_t qL[8]; ptrdiff_t numL, dif; nints= (width + Numb - 1) / Numb; size= width * height; sizeg= nints * height; #define TEST(L) \ if (L) { \ dif= true; \ for (l= 0; l < numL; l++) \ if (qL[l] == (L)) { \ dif= false; \ break; \ } \ if (dif) { \ if ((numL>0)&&(numL > cnt)) { \ c|= k; \ break; \ } \ else { \ qL[numL]= (L); \ numL+= 1; \ } \ } \ } o= out; iL00= inL; iL10= inL + size; for (n= 1; n < depth; n++) { iL01= iL00 + width; iL11= iL10 + width; for(i= 1; i < height; i++) { pL00= *(iL00++); pL01= *(iL01++); pL10= *(iL10++); pL11= *(iL11++); k= LB; c= 0; for(j= 1; j < width; j++) { numL= 0; do { TEST(pL00) TEST(pL01) TEST(pL11) TEST(pL10) TEST(*iL00) TEST(*iL01) TEST(*iL11) TEST(*iL10) } while (false); pL00= *(iL00++); pL01= *(iL01++); pL10= *(iL10++); pL11= *(iL11++); k>>= 1; if (!k) { k= LB; *(o++)= c; c= 0; } } do { TEST(pL00) TEST(pL01) TEST(pL11) TEST(pL10) TEST(pL00) TEST(pL01) TEST(pL11) TEST(pL10) } while (false); if (k != LB) *(o++)= c; } iL01= iL00; iL11= iL10; pL00= *(iL00++); pL01= *(iL01++); pL10= *(iL10++); pL11= *(iL11++); k= LB; c= 0; for(j= 1; j < width; j++) { numL= 0; do { TEST(pL00) TEST(pL01) TEST(pL11) TEST(pL10) TEST(*iL00) TEST(*iL01) TEST(*iL11) TEST(*iL10) } while (false); pL00= *(iL00++); pL01= *(iL01++); pL10= *(iL10++); pL11= *(iL11++); k>>= 1; if (!k) { k= LB; *(o++)= c; c= 0; } } do { TEST(pL00) TEST(pL01) TEST(pL11) TEST(pL10) TEST(pL00) TEST(pL01) TEST(pL11) TEST(pL10) } while (false); if (k != LB) *(o++)= c; } iL01= iL00 + width; iL10= iL00; iL11= iL10 + width; for(i= 1; i < height; i++) { pL00= *(iL00++); pL01= *(iL01++); pL10= *(iL10++); pL11= *(iL11++); k= LB; c= 0; for(j= 1; j < width; j++) { numL= 0; do { TEST(pL00) TEST(pL01) TEST(pL11) TEST(pL10) TEST(*iL00) TEST(*iL01) TEST(*iL11) TEST(*iL10) } while (false); pL00= *(iL00++); pL01= *(iL01++); pL10= *(iL10++); pL11= *(iL11++); k>>= 1; if (!k) { k= LB; *(o++)= c; c= 0; } } do { TEST(pL00) TEST(pL01) TEST(pL11) TEST(pL10) TEST(pL00) TEST(pL01) TEST(pL11) TEST(pL10) } while (false); if (k != LB) *(o++)= c; } iL01= iL00; iL11= iL10; pL00= *(iL00++); pL01= *(iL01++); pL10= *(iL10++); pL11= *(iL11++); k= LB; c= 0; for(j= 1; j < width; j++) { numL= 0; do { TEST(pL00) TEST(pL01) TEST(pL11) TEST(pL10) TEST(*iL00) TEST(*iL01) TEST(*iL11) TEST(*iL10) } while (false); pL00= *(iL00++); pL01= *(iL01++); pL10= *(iL10++); pL11= *(iL11++); k>>= 1; if (!k) { k= LB; *(o++)= c; c= 0; } } do { TEST(pL00) TEST(pL01) TEST(pL11) TEST(pL10) TEST(pL00) TEST(pL01) TEST(pL11) TEST(pL10) } while (false); if (k != LB) *(o++)= c; } #undef TEST template void Label2DBin(Image& I, Binary& image, ptrdiff_t count) { if (!image.data || !I.data) throw Allocerr(); if ((image.nDim < 2) || (image.nDim != I.nDim)) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,image.dims)) throw Sizeerr(); ptrdiff_t ints= ((I.dims[0] + Numb - 1) / Numb); ptrdiff_t width= I.dims[0]; ptrdiff_t height= I.dims[1]; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t bsize= ints * height; ptrdiff_t ssize= width * height; F *p; size_t *q; ptrdiff_t i; for (i= 0, q= image.data, p= I.data; i < numslic; i++, q+= bsize, p+= ssize) labbin2d(p, width, height, q, count); } template void Label3DBin(Image& I, Binary& image, ptrdiff_t count) { if (!image.data || !I.data) throw Allocerr(); if ((image.nDim < 3) || (image.nDim != I.nDim)) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,image.dims)) throw Sizeerr(); ptrdiff_t ints= ((I.dims[0] + Numb - 1) / Numb); ptrdiff_t width= I.dims[0]; ptrdiff_t height= I.dims[1]; ptrdiff_t depth= I.dims[2]; ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t bsize= depth * ints * height; ptrdiff_t ssize= depth * width * height; F *p; size_t *q; ptrdiff_t i; for (i= 0, q= image.data, p= I.data; i < numslic; i++, q+= bsize, p+= ssize) labbin3d(p, width, height, depth, q, count); } template void EraseBoundary2DBin (Binary& I, con2D conn = con8) { if (!I.data) throw Allocerr(); if (I.nDim < 2) throw Dimserr(); size_t k, *p, *data= I.data; ptrdiff_t i, j, n; ptrdiff_t ints= (I.dims[0] + Numb - 1) / Numb; ptrdiff_t size= ints * I.dims[1]; ptrdiff_t nimages= (I.nDim > 2)?DimsProd(I.nDim - 2, I.dims + 2):1; for (n= 0; n < nimages; n++, data+= size) { k= LB; p= data; for(i= 0; i < I.dims[1]; i++, p+= ints) if(k & *p) labelobj2d(data, I.dims[0], I.dims[1], 0, i, 0, 0, conn); k= (!(I.dims[0] % Numb))?(RB):(RB << (Numb - (I.dims[0] % Numb))); p= data + ints -1; for(i= 0; i < I.dims[1]; i++, p+= ints) if(k & *p) labelobj2d(data, I.dims[0], I.dims[1], I.dims[0] - 1, i, 0, 0, conn); p= data; for(i= 0; i < ints; i++, p++) if(*p) { k= LB; j= Numb*i; do { if(k & *p) labelobj2d(data, I.dims[0], I.dims[1], j, 0, 0, 0, conn); j++; k>>= 1; } while(k && (j < I.dims[0])); } p= data + ints * (I.dims[1] - 1); for(i= 0; i < ints; i++, p++) if(*p) { k= LB; j= Numb*i; do { if(k & *p) labelobj2d(data, I.dims[0], I.dims[1], j, I.dims[1] - 1, 0, 0, conn); j++; k>>= 1; } while(k && (j < I.dims[0])); } } } template void EraseBoundary3DBin (Binary& I, con3D conn = con18) { if (!I.data) throw Allocerr(); if (I.nDim < 3) throw Dimserr(); size_t k, *p, *data= I.data; ptrdiff_t i, j, l, n; ptrdiff_t ints= (I.dims[0] + Numb - 1) / Numb; ptrdiff_t size= ints * I.dims[1] * I.dims[2]; ptrdiff_t nimages= (I.nDim > 3)?DimsProd(I.nDim - 3, I.dims + 3):1; for (n= 0; n < nimages; n++, data+= size) { k= LB; p= data; for(j= 0; j < I.dims[1]; j++) for(l= 0; l < I.dims[2]; l++, p+= ints) if(k & *p) labelobj3d(data, I.dims[0], I.dims[1], I.dims[2], 0, j, l, 0, 0, conn); k= (!(I.dims[0] % Numb))?(RB):(RB << (Numb - (I.dims[0] % Numb))); p= data + ints - 1; for(j= 0; j < I.dims[1]; j++) for(l= 0; l < I.dims[2]; l++, p+= ints) if(k & *p) labelobj3d(data, I.dims[0], I.dims[1], I.dims[2], I.dims[0] - 1, j, l, 0, 0, conn); p= data; for(l= 0; l < I.dims[2]; l++, p+= ints * (I.dims[1] - 1)) for(i= 0; i < ints; i++, p++) if(*p != AB) { k= LB; j= Numb*i; do { if(k & *p) labelobj3d(data, I.dims[0], I.dims[1], I.dims[2], j, 0, l, 0, 0, conn); j++; k>>= 1; } while(k); } p= data + ints * (I.dims[1] - 1); for(l= 0; l < I.dims[2]; l++, p+= ints * (I.dims[1] - 1)) for(i= 0; i < ints; i++, p++) if(*p != AB) { k= LB; j= Numb*i; do { if(k & *p) labelobj3d(data, I.dims[0], I.dims[1], I.dims[2], j, I.dims[1] - 1, l, 0, 0, conn); j++; k>>= 1; } while(k); } p= data; for(l= 0; l < I.dims[1]; l++) for(i= 0; i < ints; i++, p++) if(*p != AB) { k= LB; j= Numb*i; do { if(k & *p) labelobj3d(data, I.dims[0], I.dims[1], I.dims[2], j, l, 0, 0, 0, conn); j++; k>>= 1; } while(k); } p= data + ints * I.dims[1] * (I.dims[2] - 1); for(l= 0; l < I.dims[1]; l++) for(i= 0; i < ints; i++, p++) if(*p != AB) { k= LB; j= Numb*i; do { if(k & *p) labelobj3d(data, I.dims[0], I.dims[1], I.dims[2], j, l, I.dims[2] - 1, 0, 0, conn); j++; k>>= 1; } while(k); } } } template void EvaluateObjects(Image& I, ObjectArray& L, ObjectArray& O) { if (!I.data) throw Allocerr(); for (ObjectArray::iterator io = L.begin (); io != L.end (); io++) { Object po(I.nDim + I.nVars); int i; for (i= 0; i < I.nDim; i++) po[i]=(*io)[i]; if (getpixel_gray(I.data, I.nDim, I.dims, po.data, I.bounds, I.nVars)) O.push_back(po); } } template ptrdiff_t EvaluateObject(Image& I, Object& O) { if (!I.data) throw Allocerr(); return getpixel_gray(I.data, I.nDim, I.dims, O.data, I.bounds, I.nVars); } template void SelectObjects(ObjectArray& I, ObjectArray& O, int index, double value, thrmod thr = thrgt) { for (ObjectArray::iterator io = I.begin (); io != I.end (); io++) { #define CASE(OP) \ if ((*io)[index] OP value) O.push_back(*io); \ break; switch (thr) { case thrgt: CASE(>) case thrge: CASE(>=) case thrlt: CASE(<) case thrle: CASE(<=) case thre: CASE(==) } } } #undef CASE template void ShiftObjects(ObjectArray& I, int index, double value) { for (ObjectArray::iterator io = I.begin (); io != I.end (); io++) (*io)[index]+= value; } template void PrintObjects(ObjectArray& I, int index) { for (ObjectArray::iterator io = I.begin (); io != I.end (); io++) printf("%g ",(*io)[index]); printf("\n"); fgetchar(); } template void LineProfile(Image& I, Object& x1i, Object& x2i, ObjectArray& O) { if (!I.data) throw Allocerr(); Object po(I.nDim + I.nVars); ptrdiff_t *s, poloha, index, ok, pom, i, j, maxn, isteps, m; double *p1, *p2, *p, *q, *x, *dx, max, steps, pf, *x1, *x2, *r, *dc; F *pimg; dc= new double[I.nDim]; x1= new double[I.nDim]; x2= new double[I.nDim]; memcpy(x1, x1i.data, I.nDim * sizeof(double)); memcpy(x2, x2i.data, I.nDim * sizeof(double)); for (i= 0; i < I.nDim; i++) { dc[i]= (I.bounds[2 * i + 1] - I.bounds[2 * i]) / I.dims[i]; } if (!clipline(I.nDim, x1, x2, I.bounds)) return; for (i= 0,q= I.bounds,p1= x1,p2= x2,s= I.dims,ok= false,r=dc; i < I.nDim; i++,s++,p1++,p2++,q+= 2,r++) ok|= (ptrdiff_t)((*p1 - *q) / *r) != (ptrdiff_t)((*p2 - *q)/ *r); if (!ok) { delete[] x1; delete[] x2; delete[] dc; return; } dx= new double[I.nDim]; x= new double[I.nDim]; for (i= 0; i < I.nDim; i++) { x[i]= x1[i]/* + 0.5*/; dx[i]= x2[i] - x1[i]; } for (i= 0,max= 0.0,maxn= 0; i < I.nDim; i++) if ((pf= (fabs(dx[i]) / dc[i])) > max) { max= pf; maxn= i; } steps=fabs(dx[maxn])/dc[maxn];; for (i= 0; i < I.nDim; i++) dx[i]/= steps; isteps= (ptrdiff_t)steps; for (j= 0; j <= isteps; j++) { q= I.bounds + 2 * (I.nDim - 1); p= x + (I.nDim - 1); s= I.dims + (I.nDim - 1); r= dc + (I.nDim - 1); poloha= 0; for (i= 0; i < I.nDim; i++, s--, p--, q-= 2, r--) { pom= (ptrdiff_t)((*p - *q) / *r); index= (pom >= *s)?(*s - 1):((pom < 0)?0:pom); poloha= *s * poloha + index; } for (m= 0; m < I.nDim; m++) po[m]= x[m]; pimg= I.data + poloha * I.nVars; for (m= 0; m < I.nVars; m++, pimg++) po[I.nDim + m]= *pimg; O.push_back(po); for (i= 0, p= x, q= dx; i < I.nDim; i++) *(p++)+= *(q++); } delete[] x1; delete[] x2; delete[] dc; delete[] x; delete[] dx; } template void Voxels(Image& I, ObjectArray& O) { if (!I.data) throw Allocerr(); ptrdiff_t width= I.dims[0]; double *dx= new double[I.nDim]; double *p, *q; F *i0= I.data; ptrdiff_t i, m, l, *s; for (i= 0; i < I.nDim; i++) dx[i]= I.Dx(i); ptrdiff_t ndat= DimsProd(I.nDim, I.dims); Object po(I.nDim + I.nVars); for (i= 0; i < ndat; i++) { q= I.bounds; s= I.dims; l= i; p= dx; for (m= 0, l= i; m < I.nDim; m++, q+= 2, p++, l/= *s, s++) po[m]= *q + *p * (l % *s + 0.5); for (m= 0; m < I.nVars; m++, i0++) po[I.nDim + m]= *i0; O.push_back(po); } delete[] dx; } template void BBox(Image& I, BoundBox& bb) { if (!I.data) throw Allocerr(); if (bb.nDim != I.nDim) throw Dimserr(); ptrdiff_t width= I.dims[0]; double *dx= new double[I.nDim]; double *p, *q; F *i0= I.data; ptrdiff_t i, j, m, l, *s; for (i= 0; i < I.nDim; i++) dx[i]= I.Dx(i); ptrdiff_t ndat= DimsProd(I.nDim, I.dims); for (i= 0; i < I.nDim; i++) { bb.bounds[2 * i]= I.bounds[2 * i + 1]; bb.bounds[2 * i + 1]= I.bounds[2 * i]; } for (i= 0; i < ndat; i++) { bool ok= false; for (m= 0; m < I.nVars; m++, i0++) if (*i0) ok= true; if (ok) { q= I.bounds; s= I.dims; l= i; p= dx; for (m= 0, l= i; m < I.nDim; m++, q+= 2, p++, l/= *s, s++) { double pb= *q + *p * (l % *s + 0.5); if (pb < bb.bounds[2 * m]) bb.bounds[2 * m]= pb; if (pb > bb.bounds[2 * m + 1]) bb.bounds[2 * m + 1]= pb; } } } delete[] dx; } template void VoxelsBin(Binary& I, ObjectArray& O) { if (!I.data) throw Allocerr(); ptrdiff_t width= I.dims[0]; ptrdiff_t ints= ((width + Numb - 1) / Numb); double *dx= new double[I.nDim]; double *p, *q; size_t k, *i0, *mskdat= I.data; ptrdiff_t i, j, m, l, *s; for (i= 0; i < I.nDim; i++) dx[i]= I.Dx(i); ptrdiff_t nlin= DimsProd(I.nDim - 1, I.dims + 1); Object po(I.nDim); for (i= 0; i < nlin; i++, mskdat+= ints) { k= LB; i0= mskdat; for (j= 0; j < width; j++) { if (k & *i0) { q= I.bounds; po[0]= *q + (j + 0.5) * *dx; q+= 2; s= I.dims + 1; l= i; p= dx + 1; for (m= 1; m < I.nDim; m++, q+= 2, p++, l/= *s, s++) po[m]= *q + *p * (l % *s + 0.5); O.push_back(po); } k>>= 1; if (k == 0) { k= LB; i0++; } } } delete[] dx; } template void BBoxBin(Binary& I, BoundBox& bb) { if (!I.data) throw Allocerr(); if (bb.nDim != I.nDim) throw Dimserr(); ptrdiff_t width= I.dims[0]; ptrdiff_t ints= ((width + Numb - 1) / Numb); double *dx= new double[I.nDim]; double *p, *q; size_t k, *i0, *mskdat= I.data; ptrdiff_t i, j, m, l, *s; for (i= 0; i < I.nDim; i++) dx[i]= I.Dx(i); ptrdiff_t nlin= DimsProd(I.nDim - 1, I.dims + 1); for (i= 0; i < I.nDim; i++) { bb.bounds[2 * i]= I.bounds[2 * i + 1]; bb.bounds[2 * i + 1]= I.bounds[2 * i]; } for (i= 0; i < nlin; i++, mskdat+= ints) { k= LB; i0= mskdat; for (j= 0; j < width; j++) { if (k & *i0) { q= I.bounds; double pb= *q + (j + 0.5) * *dx; if (pb < bb.bounds[0]) bb.bounds[0]= pb; if (pb > bb.bounds[1]) bb.bounds[1]= pb; q+= 2; s= I.dims + 1; l= i; p= dx + 1; for (m= 1; m < I.nDim; m++, q+= 2, p++, l/= *s, s++) { pb= *q + *p * (l % *s + 0.5); if (pb < bb.bounds[2 * m]) bb.bounds[2 * m]= pb; if (pb > bb.bounds[2 * m + 1]) bb.bounds[2 * m + 1]= pb; } } k>>= 1; if (k == 0) { k= LB; i0++; } } } delete[] dx; } class Edge2D_GD { public: Edge2D_GD(ptrdiff_t ix, ptrdiff_t iy, float iv) : x(ix), y(iy), v(iv) {} ptrdiff_t x, y; float v; }; inline bool operator<(const Edge2D_GD a1, const Edge2D_GD a2) { return (a1.v > a2.v); } template void geodesic_distance2D(float *image, size_t *mask, size_t *init, ptrdiff_t width, ptrdiff_t height, double dx, double dy, con2D conn) { size_t c, k; ptrdiff_t numint, x, y, clen, x32, i, j, n; size_t *p, *p1, *p2; std::priority_queue pque; float val, value; numint = (width + Numb - 1) / Numb; #define PUSHQUE(X,Y,V) \ pque.push(Edge2D_GD(X,Y,V)); c = ((width % Numb) == 0) ? (AB) : (AB << (Numb - (width % Numb))); clen = ((width % Numb) == 0) ? Numb : (Numb - (width % Numb)); if (numint > 0) { p1 = init; for (i = 1; i < numint; i++, p1++) { for (j = 0, p2 = p1; j < height; j++, p2+= numint) if (*p2) { k = LB; for (n = 0; n < Numb; n++, k >>= 1) if (k&*p2) { PUSHQUE((i - 1) * Numb + n, j, 0.) } } } } for (j = 0, p2 = p1; j < height; j++, p2 += numint) if (*p2) { k = LB; for (n = 0; n < clen; n++, k >>= 1) if (k&*p2) { PUSHQUE((numint - 1) * Numb + n, j, 0.) } } #define POPQUE(X,Y,V) \ X= pque.top().x; \ Y= pque.top().y; \ V= pque.top().v; \ pque.pop(); #define TEST(newx,newy,newval) \ if (*(image + ((newy)* width + newx))==max_float) { \ x32 = (newx) / Numb; \ p = mask + ((newy) * numint + x32); \ k = LB >> ((newx) % Numb); \ if (k & *p) { \ PUSHQUE(newx, newy, newval) \ } \ } double dxy = sqrt(dx*dx + dy*dy); while (!pque.empty()) { POPQUE(x, y, val) value = *(image + (y * width + x)); if (val < value) { *(image + (y * width + x)) = val; if (y < (height - 1)) { TEST(x, y + 1, val + dy) } if (x < (width - 1)) { TEST(x + 1, y, val + dx) } if (x > 0) { TEST(x - 1, y, val + dx) } if (y > 0) { TEST(x, y - 1, val + dy) } if (conn == con8) { if (x < (width - 1)) { if (y < (height - 1)) { TEST(x + 1, y + 1, val + dxy) } if (y > 0) { TEST(x + 1, y - 1, val + dxy) } } if (x > 0) { if (y < (height - 1)) { TEST(x - 1, y + 1, val + dxy) } if (y > 0) { TEST(x - 1, y - 1, val + dxy) } } } } } } #undef TEST #undef PUSHQUE #undef PUSHQUEV #undef POPQUE template void DistanceGeodesic2D (Binary& I, Binary& M, Image& O) { if ((!O.data)||(!I.data)||(!M.data)) throw Allocerr(); if ((I.nDim != 2) || (M.nDim != 2) || (O.nDim != 2)) throw Dimserr(); if (O.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,M.dims) || !DimsEq(I.nDim,I.dims,O.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t slisize= DimsProd(2, I.dims); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1]; O.SetData(IL_GU_SET, max_float); float *p; size_t *q, *r; ptrdiff_t i; for (i= 0, q= I.data, r= M.data, p= O.data; i < numslic; i++, q+= step, r+= step, p+= slisize) { geodesic_distance2D(p, r, q, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), con8); } Combine(O, M, 0., binneg); } class Edge3D_GD { public: Edge3D_GD(ptrdiff_t ix, ptrdiff_t iy, ptrdiff_t iz, float iv) : x(ix), y(iy), z(iz), v(iv) {} ptrdiff_t x, y, z; float v; }; inline bool operator<(const Edge3D_GD a1, const Edge3D_GD a2) { return (a1.v > a2.v); } template void geodesic_distance3D(float *image, size_t *mask, size_t *init, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, con3D conn) { size_t c, k; ptrdiff_t numint, x, y, z, clen, x32, i, j, l, n; size_t *p, *p1, *p2; std::priority_queue pque; float val, value; numint = (width + Numb - 1) / Numb; #define PUSHQUE(X,Y,Z,V) \ pque.push(Edge3D_GD(X,Y,Z,V)); c = ((width % Numb) == 0) ? (AB) : (AB << (Numb - (width % Numb))); clen = ((width % Numb) == 0) ? Numb : (Numb - (width % Numb)); if (numint > 0) { p1 = init; for (i = 1; i < numint; i++, p1++) { for (l = 0, p2 = p1; l < depth; l++) for (j = 0; j < height; j++, p2+= numint) if (*p2) { k = LB; for (n = 0; n < Numb; n++, k >>= 1) if (k&*p2) { PUSHQUE((i - 1) * Numb + n, j, l, 0.) } } } } for (l = 0, p2 = p1; l < depth; l++) for (j = 0; j < height; j++, p2 += numint) if (*p2) { k = LB; for (n = 0; n < clen; n++, k >>= 1) if (k&*p2) { PUSHQUE((numint - 1) * Numb + n, j, l, 0.) } } #define POPQUE(X,Y,Z,V) \ X= pque.top().x; \ Y= pque.top().y; \ Z= pque.top().z; \ V= pque.top().v; \ pque.pop(); #define TEST(newx,newy,newz,newval) \ if (*(image + (((newz) * height + newy) * width + newx))==max_float) { \ x32 = (newx) / Numb; \ p = mask + (((newz) * height + newy) * numint + x32); \ k = LB >> ((newx) % Numb); \ if (k & *p) { \ PUSHQUE(newx, newy, newz, newval) \ } \ } double dxy = sqrt(dx*dx + dy*dy); double dxz = sqrt(dx*dx + dz*dz); double dyz = sqrt(dy*dy + dz*dz); double dxyz = sqrt(dx*dx + dy*dy + dz*dz); while (!pque.empty()) { POPQUE(x, y, z, val) value = *(image + ((z * height + y) * width + x)); if (val < value) { *(image + ((z * height + y) * width + x)) = val; if (x > 0) { TEST(x - 1, y, z, val + dx) } if (x < (width - 1)) { TEST(x + 1, y, z, val + dx) } if (y > 0) { TEST(x, y - 1, z, val + dy) } if (y < (height - 1)) { TEST(x, y + 1, z, val + dy) } if (z > 0) { TEST(x, y, z - 1, val + dz) } if (z < (depth - 1)) { TEST(x, y, z + 1, val + dz) } if (conn != con6) { if (x > 0) { if (y > 0) { TEST(x - 1, y - 1, z, val + dxy) } if (y < (height - 1)) { TEST(x - 1, y + 1, z, val + dxy) } } if (x < (width - 1)) { if (y > 0) { TEST(x + 1, y - 1, z, val + dxy) } if (y < (height - 1)) { TEST(x + 1, y + 1, z, val + dxy) } } if (x > 0) { if (z > 0) { TEST(x - 1, y, z - 1, val + dxz) } if (z < (depth - 1)) { TEST(x - 1, y, z + 1, val + dxz) } } if (x < (width - 1)) { if (z > 0) { TEST(x + 1, y, z - 1, val + dxz) } if (z < (depth - 1)) { TEST(x + 1, y, z + 1, val + dxz) } } if (y > 0) { if (z > 0) { TEST(x, y - 1, z - 1, val + dyz) } if (z < (depth - 1)) { TEST(x, y - 1, z + 1, val + dyz) } } if (y < (height - 1)) { if (z > 0) { TEST(x, y + 1, z - 1, val + dyz) } if (z < (depth - 1)) { TEST(x, y + 1, z + 1, val + dyz) } } } } } } #undef TEST #undef PUSHQUE #undef PUSHQUEV #undef POPQUE template void DistanceGeodesic3D (Binary& I, Binary& M, Image& O) { if ((!O.data)||(!I.data)||(!M.data)) throw Allocerr(); if ((I.nDim != 3) || (M.nDim != 3) || (O.nDim != 3)) throw Dimserr(); if (O.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,M.dims) || !DimsEq(I.nDim,I.dims,O.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t slisize= DimsProd(3, I.dims); ptrdiff_t step= ((I.dims[0] + Numb - 1) / Numb) * I.dims[1] * I.dims[2]; O.SetData(IL_GU_SET, max_float); float *p; size_t *q, *r; ptrdiff_t i; for (i= 0, q= I.data, r= M.data, p= O.data; i < numslic; i++, q+= step, r+= step, p+= slisize) { geodesic_distance3D(p, r, q, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), con18); } Combine(O, M, 0., binneg); } template void Maxima1D (Image& I, Binary& B, const F value) { if (!I.data || !B.data) throw Allocerr(); if ((!I.nDim)||(B.nDim != I.nDim)) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,B.dims)) throw Sizeerr(); ptrdiff_t nints= (I.dims[0]+Numb - 1)/Numb; ptrdiff_t size= I.dims[0]; ptrdiff_t bsize= nints; ptrdiff_t nimages= (I.nDim > 1)?DimsProd(I.nDim - 1, I.dims + 1):1; Binary OutImage(1, I.dims); OutImage.data= B.data; Image InImage(1, I.dims); Img PImage(1, I.dims); InImage.data= I.data; ptrdiff_t i; for (i= 0; i < nimages; i++) { PImage.SetData(InImage.data); PImage.SetData(IL_GU_MINUS,value); Reconstruct1D(PImage, InImage); PImage.SetData(IL_GB_SUB, InImage.data); Threshold(PImage, OutImage, value, thrge); InImage.data+= size; OutImage.data+= bsize; } B.EraseEnd(); return; } template void Maxima1D (Image& I, Binary& B, const F value1, const F value2) { if (!I.data || !B.data) throw Allocerr(); if ((!I.nDim)||(B.nDim != I.nDim)) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,B.dims)) throw Sizeerr(); ptrdiff_t nints= (I.dims[0]+Numb - 1)/Numb; ptrdiff_t size= I.dims[0]; ptrdiff_t bsize= nints; ptrdiff_t nimages= (I.nDim > 1)?DimsProd(I.nDim - 1, I.dims + 1):1; Binary OutImage(1, I.dims); OutImage.data= B.data; Image InImage(1, I.dims); Img PImage(1, I.dims); Bin QImage(1, I.dims); InImage.data= I.data; ptrdiff_t i; for (i= 0; i < nimages; i++) { PImage.SetData(InImage.data); PImage.SetData(IL_GU_MINUS,value1); Reconstruct1D(PImage, InImage); PImage.SetData(IL_GB_SUB, InImage.data); Threshold(PImage, QImage, value2, thrge); Threshold(PImage, OutImage, value1, thrge); Reconstruct1DBin(OutImage, QImage); InImage.data+= size; OutImage.data+= bsize; } B.EraseEnd(); return; } template void Maxima2D (Image& I, Binary& B, const F value1, const F value2, con2D conn) { if (!I.data || !B.data) throw Allocerr(); if ((I.nDim < 2)||(B.nDim != I.nDim)) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,B.dims)) throw Sizeerr(); ptrdiff_t nints= (I.dims[0]+Numb - 1)/Numb; ptrdiff_t size= I.dims[0] * I.dims[1]; ptrdiff_t bsize= nints * I.dims[1]; ptrdiff_t nimages= (I.nDim > 2)?DimsProd(I.nDim - 2, I.dims + 2):1; Binary OutImage(2, I.dims); OutImage.data= B.data; Image InImage(2, I.dims); Img PImage(2, I.dims); Bin QImage(2, I.dims); InImage.data= I.data; ptrdiff_t i; for (i= 0; i < nimages; i++) { PImage.SetData(InImage.data); PImage.SetData(IL_GU_MINUS,value1); Reconstruct2D(PImage, InImage, conn, rectot); PImage.SetData(IL_GB_SUB, InImage.data); Threshold(PImage, QImage, value2, thrge); Threshold(PImage, OutImage, value1, thrge); Reconstruct2DBin(OutImage, QImage, conn); InImage.data+= size; OutImage.data+= bsize; } B.EraseEnd(); return; } template void Maxima2D (Image& I, Binary& B, const F value, con2D conn) { if (!I.data || !B.data) throw Allocerr(); if ((I.nDim < 2)||(B.nDim != I.nDim)) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,B.dims)) throw Sizeerr(); ptrdiff_t nints= (I.dims[0]+Numb - 1)/Numb; ptrdiff_t size= I.dims[0] * I.dims[1]; ptrdiff_t bsize= nints * I.dims[1]; ptrdiff_t nimages= (I.nDim > 2)?DimsProd(I.nDim - 2, I.dims + 2):1; Binary OutImage(2, I.dims); OutImage.data= B.data; Image InImage(2, I.dims); Img PImage(2, I.dims); InImage.data= I.data; ptrdiff_t i; for (i= 0; i < nimages; i++) { PImage.SetData(InImage.data); PImage.SetData(IL_GU_MINUS,value); Reconstruct2D(PImage, InImage, conn, rectot); PImage.SetData(IL_GB_SUB, InImage.data); Threshold(PImage, OutImage, value, thrge); InImage.data+= size; OutImage.data+= bsize; } B.EraseEnd(); return; } template void Maxima3D (Image& I, Binary& B, const F value1, const F value2, con3D conn) { if (!I.data || !B.data) throw Allocerr(); if ((I.nDim < 3)||(B.nDim != I.nDim)) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,B.dims)) throw Sizeerr(); ptrdiff_t nints= (I.dims[0]+Numb - 1)/Numb; ptrdiff_t size= I.dims[0] * I.dims[1] * I.dims[2]; ptrdiff_t bsize= nints * I.dims[1] * I.dims[2]; ptrdiff_t nimages= (I.nDim > 3)?DimsProd(I.nDim - 3, I.dims + 3):1; Binary OutImage(3, I.dims); OutImage.data= B.data; Image InImage(3, I.dims); Img PImage(3, I.dims); Bin QImage(3, I.dims); InImage.data= I.data; ptrdiff_t i; for (i= 0; i < nimages; i++) { PImage.SetData(InImage.data); PImage.SetData(IL_GU_MINUS,value1); Reconstruct3D(PImage, InImage, conn, rectot); PImage.SetData(IL_GB_SUB, InImage.data); Threshold(PImage, QImage, value2, thrge); Threshold(PImage, OutImage, value1, thrge); Reconstruct3DBin(OutImage, QImage, conn); InImage.data+= size; OutImage.data+= bsize; } B.EraseEnd(); return; } template void Maxima3D (Image& I, Binary& B, const F value, con3D conn) { if (!I.data || !B.data) throw Allocerr(); if ((I.nDim < 3)||(B.nDim != I.nDim)) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,B.dims)) throw Sizeerr(); ptrdiff_t nints= (I.dims[0]+Numb - 1)/Numb; ptrdiff_t size= I.dims[0] * I.dims[1] * I.dims[2]; ptrdiff_t bsize= nints * I.dims[1] * I.dims[2]; ptrdiff_t nimages= (I.nDim > 3)?DimsProd(I.nDim - 3, I.dims + 3):1; Binary OutImage(3, I.dims); OutImage.data= B.data; Image InImage(3, I.dims); Img PImage(3, I.dims); InImage.data= I.data; ptrdiff_t i; for (i= 0; i < nimages; i++) { PImage.SetData(InImage.data); PImage.SetData(IL_GU_MINUS,value); Reconstruct3D(PImage, InImage, conn, rectot); PImage.SetData(IL_GB_SUB, InImage.data); Threshold(PImage, OutImage, value, thrge); InImage.data+= size; OutImage.data+= bsize; } B.EraseEnd(); return; } inline bool predicate_obj2(const Object x1, const Object x2) { //< return (x1[2] > x2[2])?1:0; } inline bool predicate_obj3(const Object x1, const Object x2) { //< return (x1[3] > x2[3])?1:0; } inline bool predicate_obj4(const Object x1, const Object x2) { //< return (x1[4] > x2[4])?1:0; } template void OpenArea2D (Image& I, const ptrdiff_t minsize, con2D conn, int dir) { if (!I.data) throw Allocerr(); if (I.nDim < 2) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t size= I.dims[0] * I.dims[1]; ptrdiff_t nimages= (I.nDim > 2)?DimsProd(I.nDim - 2, I.dims + 2):1; Bin BImage(2, I.dims); Bin BImage2(2, I.dims); Image InImage(2, I.dims); InImage.data= I.data; ObjectArray O1, O2; F maxv= ~0; ptrdiff_t i; for (i= 0; i < nimages; i++) { if (dir) InImage.SetData(IL_GU_SUB, maxv); Maxima2D(InImage,BImage,(F)1, conn); //TODO: float images MeasureObjects2DBin(BImage, O1, conn); //PrintObjects(O1, 2); SelectObjects(O1, O2, 4, minsize, thrle); //TODO: size only once O1.clear(); EvaluateObjects(InImage, O2, O1); O2.clear(); //necessary? std::sort(O1.begin(),O1.end(),predicate_obj2); BImage2.SetData(IL_BU_SET); F value= maxv; for (ObjectArray::iterator io = O1.begin (); io != O1.end (); io++) { open_area2D(InImage.data,BImage.data,BImage2.data,I.dims[0],I.dims[1], (*io)[0],(*io)[1],minsize,value,conn); labelobj2d(BImage2.data,I.dims[0],I.dims[1],(*io)[0],(*io)[1], InImage.data, value, conn); } O1.clear(); if (dir) InImage.SetData(IL_GU_SUB, maxv); InImage.data+= size; } } template void OpenAreaTopHat2D (Image& I, const ptrdiff_t minsize, con2D conn, int dir) { if (!I.data) throw Allocerr(); if (I.nDim < 2) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t size= I.dims[0] * I.dims[1]; ptrdiff_t nimages= (I.nDim > 2)?DimsProd(I.nDim - 2, I.dims + 2):1; Bin BImage(2, I.dims); Bin BImage2(2, I.dims); Image InImage(2, I.dims); Img PImage(2, I.dims); InImage.data= I.data; ObjectArray O1, O2; F maxv= ~0; ptrdiff_t i; for (i= 0; i < nimages; i++) { if (dir) InImage.SetData(IL_GU_SUB, maxv); PImage.SetData(InImage.data); Maxima2D(InImage,BImage,(F)1, conn); //TODO: float images MeasureObjects2DBin(BImage, O1, conn); //PrintObjects(O1, 2); SelectObjects(O1, O2, 4, minsize, thrle); //TODO: size only once O1.clear(); EvaluateObjects(InImage, O2, O1); O2.clear(); //necessary? std::sort(O1.begin(),O1.end(),predicate_obj2); BImage2.SetData(IL_BU_SET); F value= maxv; for (ObjectArray::iterator io = O1.begin (); io != O1.end (); io++) { open_area2D(InImage.data,BImage.data,BImage2.data,I.dims[0],I.dims[1], (*io)[0],(*io)[1],minsize,value,conn); labelobj2d(BImage2.data,I.dims[0],I.dims[1],(*io)[0],(*io)[1], InImage.data, value, conn); } O1.clear(); InImage.SetData(IL_GB_SUB,PImage.data); if (dir) InImage.SetData(IL_GU_SUB, maxv); InImage.data+= size; } } template void OpenVolume3D (Image& I, const ptrdiff_t minsize, con3D conn, int dir) { if (!I.data) throw Allocerr(); if (I.nDim < 3) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t size= I.dims[0] * I.dims[1] * I.dims[2]; ptrdiff_t nimages= (I.nDim > 3)?DimsProd(I.nDim - 3, I.dims + 3):1; Bin BImage(3, I.dims); Bin BImage2(3, I.dims); Image InImage(3, I.dims); InImage.data= I.data; ObjectArray O1, O2; F maxv= ~0; ptrdiff_t i; for (i= 0; i < nimages; i++) { if (dir) InImage.SetData(IL_GU_SUB, maxv); Maxima3D(InImage,BImage,(F)1, conn); //TODO: float images MeasureObjects3DBin(BImage, O1, conn); //printf("%d\n",O1.size()); SelectObjects(O1, O2, 6, minsize, thrle); //printf("%d\n",O2.size()); //PrintObjects(O2, 3); //TODO: size only once O1.clear(); EvaluateObjects(InImage, O2, O1); //printf("%d\n",O2.size()); O2.clear(); //necessary? std::sort(O1.begin(),O1.end(),predicate_obj3); //PrintObjects(O1, 3); BImage2.SetData(IL_BU_SET); F value= maxv; for (ObjectArray::iterator io = O1.begin (); io != O1.end (); io++) { open_volume3D(InImage.data,BImage.data,BImage2.data,I.dims[0],I.dims[1],I.dims[2], (*io)[0],(*io)[1],(*io)[2],minsize,value,conn); labelobj3d(BImage2.data,I.dims[0],I.dims[1],I.dims[2],(*io)[0],(*io)[1],(*io)[2], InImage.data, value, conn); } O1.clear(); if (dir) InImage.SetData(IL_GU_SUB, maxv); InImage.data+= size; } } template void OpenVolumeTopHat3D (Image& I, const ptrdiff_t minsize, con3D conn, int dir) { if (!I.data) throw Allocerr(); if (I.nDim < 3) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t size= I.dims[0] * I.dims[1] * I.dims[2]; ptrdiff_t nimages= (I.nDim > 3)?DimsProd(I.nDim - 3, I.dims + 3):1; Bin BImage(3, I.dims); Bin BImage2(3, I.dims); Image InImage(3, I.dims); Img PImage(3, I.dims); InImage.data= I.data; ObjectArray O1, O2; F maxv= ~0; ptrdiff_t i; for (i= 0; i < nimages; i++) { if (dir) InImage.SetData(IL_GU_SUB, maxv); PImage.SetData(InImage.data); Maxima3D(InImage,BImage,(F)1, conn); //TODO: float images MeasureObjects3DBin(BImage, O1, conn); //printf("%d\n",O1.size()); SelectObjects(O1, O2, 6, minsize, thrle); //printf("%d\n",O2.size()); //PrintObjects(O2, 3); //TODO: size only once O1.clear(); EvaluateObjects(InImage, O2, O1); //printf("%d\n",O2.size()); O2.clear(); //necessary? std::sort(O1.begin(),O1.end(),predicate_obj3); //PrintObjects(O1, 3); BImage2.SetData(IL_BU_SET); F value= maxv; for (ObjectArray::iterator io = O1.begin (); io != O1.end (); io++) { open_volume3D(InImage.data,BImage.data,BImage2.data,I.dims[0],I.dims[1],I.dims[2], (*io)[0],(*io)[1],(*io)[2],minsize,value,conn); labelobj3d(BImage2.data,I.dims[0],I.dims[1],I.dims[2],(*io)[0],(*io)[1],(*io)[2], InImage.data, value, conn); } O1.clear(); InImage.SetData(IL_GB_SUB,PImage.data); if (dir) InImage.SetData(IL_GU_SUB, maxv); InImage.data+= size; } } template class MedianBuff { //rather slow std::multiset> ls; std::multiset gs; size_t mdn; public: MedianBuff() { mdn= 0; } void Push(unsigned char v) { if (v < mdn) ls.insert(v); else gs.insert(v); } void Pop(unsigned char v) { if (v < mdn) { std::multiset>::iterator it= ls.find(v); if (it != ls.end()) ls.erase(it); else gs.erase(gs.find(v)); } else { std::multiset::iterator it= gs.find(v); if (it != gs.end()) gs.erase(it); else ls.erase(ls.find(v)); } } size_t Median() { //test? int num= ls.size() + gs.size(); size_t lnm2= num / 2; if (ls.size() > lnm2) do { //ls to gs gs.insert(*ls.begin()); ls.erase(ls.begin()); } while (ls.size() > lnm2); else while (gs.size() > (num - lnm2)) { //gs to ls ls.insert(*gs.begin()); gs.erase(gs.begin()); } mdn= *gs.begin(); return mdn; } }; template void median2d(F *pd, ptrdiff_t width, ptrdiff_t height, ptrdiff_t size, F *qd) { F *p= pd; F *q= qd; int sz1= size / 2; int sz2= size - sz1; for (int i= 0; i < height; i++) { int i1= (i > sz1)?(i - sz1):0; int i2= (i < (height - sz2))?(i + sz2):height; MedianBuff mb; F *r= p; for (int j= 1; j < sz2; j++, r++) { F *s= r - (i - i1) * width; for (int ii= i1; ii < i2; ii++, s+= width) mb.Push(*s); } for (int j= 0; j < width; j++, p++, q++) { if (j <= (width - sz2)) { F *s= p + sz2 - 1 - (i - i1) * width; for (int ii= i1; ii < i2; ii++, s+= width) mb.Push(*s); } if (j > sz1) { F *s= p - sz1 - 1 - (i - i1) * width; for (int ii= i1; ii < i2; ii++, s+= width) mb.Pop(*s); } *q= mb.Median(); } } } template void MedianFilter2D (Image& I, const ptrdiff_t size) { if (!I.data) throw Allocerr(); if (I.nDim < 2) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F *q= I.data; F *pdat= new F[step]; for (int i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(F)); median2d(pdat, I.dims[0], I.dims[1], size, q); q+= step; } delete [] pdat; } template void median3d(F *pd, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, ptrdiff_t size, const ptrdiff_t sizez, F *qd) { F *p= pd; F *q= qd; int sz1= size / 2; int sz2= size - sz1; int szz1= sizez / 2; int szz2= sizez - szz1; ptrdiff_t sizexy= width * height; for (int i= 0; i < depth; i++) { int i1= (i > szz1)?(i - szz1):0; int i2= (i < (depth - szz2))?(i + szz2):depth; for (int j= 0; j < height; j++) { int j1= (j > sz1)?(j - sz1):0; int j2= (j < (height - sz2))?(j + sz2):height; MedianBuff mb; F *r= p; for (int k= 1; k < sz2; k++, r++) { F *s= r - (i - i1) * sizexy - (j - j1) * width; for (int ii= i1; ii < i2; ii++, s+= sizexy) { F *t= s; for (int jj= j1; jj < j2; jj++, t+= width) mb.Push(*t); } } for (int k= 0; k < width; k++, p++, q++) { if (k <= (width - sz2)) { F *s= r - (i - i1) * sizexy - (j - j1) * width; for (int ii= i1; ii < i2; ii++, s+= sizexy) { F *t= s; for (int jj= j1; jj < j2; jj++, t+= width) mb.Push(*t); } r++; } if (k > sz1) { F *s= p - sz1 - 1 - (i - i1) * sizexy - (j - j1) * width; for (int ii= i1; ii < i2; ii++, s+= sizexy) { F *t= s; for (int jj= j1; jj < j2; jj++, t+= width) mb.Pop(*t); } } *q= mb.Median(); } } } } template void MedianFilter3D (Image& I, const ptrdiff_t size, const ptrdiff_t sizez) { if (!I.data) throw Allocerr(); if (I.nDim < 3) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F *q= I.data; F *pdat= new F[step]; for (int i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(F)); median3d(pdat, I.dims[0], I.dims[1], I.dims[2], size, sizez, q); q+= step; } delete [] pdat; } class MedianBuffCh { size_t Hist[256]; size_t num, mdn, ltmdn; public: MedianBuffCh() { for (int i= 0; i < 256; i++) Hist[i]= 0; num= 0.; mdn= 0; ltmdn= 0; } void Push(unsigned char v) { Hist[v]++; num++; if (v < mdn) ltmdn++; } void Pop(unsigned char v) { Hist[v]--; //test? num--; if (v < mdn) ltmdn--; } size_t Median() { //test? size_t lnm2= num / 2; if (ltmdn > lnm2) do { mdn--; ltmdn-= Hist[mdn]; } while (ltmdn > lnm2); else while ((ltmdn + Hist[mdn]) <= lnm2) { ltmdn+= Hist[mdn]; mdn++; } return mdn; } }; template void median2d(unsigned char *pd, ptrdiff_t width, ptrdiff_t height, ptrdiff_t size, unsigned char *qd) { unsigned char *p= pd; unsigned char *q= qd; int sz1= size / 2; int sz2= size - sz1; for (int i= 0; i < height; i++) { int i1= (i > sz1)?(i - sz1):0; int i2= (i < (height - sz2))?(i + sz2):height; MedianBuffCh mb; unsigned char *r= p; for (int j= 1; j < sz2; j++, r++) { unsigned char *s= r - (i - i1) * width; for (int ii= i1; ii < i2; ii++, s+= width) mb.Push(*s); } for (int j= 0; j < width; j++, p++, q++) { if (j <= (width - sz2)) { unsigned char *s= r - (i - i1) * width; for (int ii= i1; ii < i2; ii++, s+= width) mb.Push(*s); r++; } if (j > sz1) { unsigned char *s= p - sz1 - 1 - (i - i1) * width; for (int ii= i1; ii < i2; ii++, s+= width) mb.Pop(*s); } *q= mb.Median(); } } } template void MedianFilter2D (Image& I, const ptrdiff_t size) { if (!I.data) throw Allocerr(); if (I.nDim < 2) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; unsigned char *q= I.data; unsigned char *pdat= new unsigned char[step]; for (int i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(unsigned char)); median2d(pdat, I.dims[0], I.dims[1], size, q); q+= step; } delete [] pdat; } template void median3d(unsigned char *pd, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, ptrdiff_t size, const ptrdiff_t sizez, unsigned char *qd) { unsigned char *p= pd; unsigned char *q= qd; int sz1= size / 2; int sz2= size - sz1; int szz1= sizez / 2; int szz2= sizez - szz1; ptrdiff_t sizexy= width * height; for (int i= 0; i < depth; i++) { int i1= (i > szz1)?(i - szz1):0; int i2= (i < (depth - szz2))?(i + szz2):depth; for (int j= 0; j < height; j++) { int j1= (j > sz1)?(j - sz1):0; int j2= (j < (height - sz2))?(j + sz2):height; MedianBuffCh mb; unsigned char *r= p; for (int k= 1; k < sz2; k++, r++) { unsigned char *s= r - (i - i1) * sizexy - (j - j1) * width; for (int ii= i1; ii < i2; ii++, s+= sizexy) { unsigned char *t= s; for (int jj= j1; jj < j2; jj++, t+= width) mb.Push(*t); } } for (int k= 0; k < width; k++, p++, q++) { if (k <= (width - sz2)) { unsigned char *s= r - (i - i1) * sizexy - (j - j1) * width; for (int ii= i1; ii < i2; ii++, s+= sizexy) { unsigned char *t= s; for (int jj= j1; jj < j2; jj++, t+= width) mb.Push(*t); } r++; } if (k > sz1) { unsigned char *s= p - sz1 - 1 - (i - i1) * sizexy - (j - j1) * width; for (int ii= i1; ii < i2; ii++, s+= sizexy) { unsigned char *t= s; for (int jj= j1; jj < j2; jj++, t+= width) mb.Pop(*t); } } *q= mb.Median(); } } } } template void MedianFilter3D (Image& I, const ptrdiff_t size, const ptrdiff_t sizez) { if (!I.data) throw Allocerr(); if (I.nDim < 3) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; unsigned char *q= I.data; unsigned char *pdat= new unsigned char[step]; for (int i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(unsigned char)); median3d(pdat, I.dims[0], I.dims[1], I.dims[2], size, sizez, q); q+= step; } delete [] pdat; } template void gradient_2d_vec_0(F* in, G* out, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double mult) { F *i0, *i1; G *o; ptrdiff_t i, j; double s1, s2, d1, d2, gx, gy, ddy, ddx, sp; #define RDVAL \ s1= (double)*i0 + (double)*i1; \ d1= (double)*i1 - (double)*i0; #define INC \ i0++; i1++; #define VYP \ RDVAL \ for(j= 1; j < width; j++) { \ s2= s1; \ d2= d1; \ INC \ RDVAL \ gx= (s1 - s2) / ddx; \ gy= (d1 + d2) / ddy; \ *(o++)= mult * gx; \ *(o++)= mult * gy; \ } \ INC \ *(o++)= mult * gx; \ *(o++)= mult * gy; o= out; sp= sqrt((dx * dx + dy * dy) / 2.0); ddx= 2.0 * dx / sp; ddy= 2.0 * dy / sp; i0= in; i1= i0 + width; for(i= 1; i < height; i++) { VYP } for(j= 0; j < width; j++) { *(o++)= *(o - 2 * width); *(o++)= *(o - 2 * width); } #undef VYP } template void gradient_2d_abs_0(F* in, G* out, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double mult) { F *i0, *i1; G *o; ptrdiff_t i, j; double s1, s2, d1, d2, gx, gy, ddy, ddx, sp; #define VYP \ RDVAL \ for(j= 1; j < width; j++) { \ s2= s1; \ d2= d1; \ INC \ RDVAL \ gx= (s1 - s2) / ddx; \ gy= (d1 + d2) / ddy; \ *(o++)= mult * sqrt(gy * gy + gx * gx); \ } \ INC \ *(o++)= mult * sqrt(gy * gy + gx * gx); o= out; sp= sqrt((dx * dx + dy * dy) / 2.0); ddx= 2.0 * dx / sp; ddy= 2.0 * dy / sp; i0= in; i1= i0 + width; for(i= 1; i < height; i++) { VYP } for(j= 0; j < width; j++) { *(o++)= *(o - width); } #undef VYP } template void gradient_2d_abs_vec_0(F* in, G* out, G* vec, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double mult) { F *i0, *i1; G *o; G *v; ptrdiff_t i, j; double s1, s2, d1, d2, gx, gy, ddy, ddx, sp; #define VYP \ RDVAL \ for(j= 1; j < width; j++) { \ s2= s1; \ d2= d1; \ INC \ RDVAL \ gx= (s1 - s2) / ddx; \ gy= (d1 + d2) / ddy; \ *(v++)= mult * gx; \ *(v++)= mult * gy; \ *(o++)= mult * sqrt(gy * gy + gx * gx); \ } \ INC \ *(v++)= mult * gx; \ *(v++)= mult * gy; \ *(o++)= mult * sqrt(gy * gy + gx * gx); o= out; v= vec; sp= sqrt((dx * dx + dy * dy) / 2.0); ddx= 2.0 * dx / sp; ddy= 2.0 * dy / sp; i0= in; i1= i0 + width; for(i= 1; i < height; i++) { VYP } for(j= 0; j < width; j++) { *(o++)= *(o - width); *(v++)= *(v - 2 * width); *(v++)= *(v - 2 * width); } #undef VYP } template void gradient_2d_abs_ten_0(F* in, G* out, G* ten, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double mult) { F *i0, *i1; G *o, *t; ptrdiff_t i, j; double s1, s2, d1, d2, gx, gy, ddy, ddx, sp; #define VYP \ RDVAL \ for(j= 1; j < width; j++) { \ s2= s1; \ d2= d1; \ INC \ RDVAL \ gx= (s1 - s2) / ddx; \ gy= (d1 + d2) / ddy; \ *(t++)= mult * gx * gx; \ *(t++)= mult * gx * gy; \ *(t++)= mult * gy * gy; \ *(o++)= mult * sqrt(gy * gy + gx * gx); \ } \ INC \ *(t++)= mult * gx * gx; \ *(t++)= mult * gx * gy; \ *(t++)= mult * gy * gy; \ *(o++)= mult * sqrt(gy * gy + gx * gx); o= out; t= ten; sp= sqrt((dx * dx + dy * dy) / 2.0); ddx= 2.0 * dx / sp; ddy= 2.0 * dy / sp; i0= in; i1= i0 + width; for(i= 1; i < height; i++) { VYP } for(j= 0; j < width; j++) { *(o++)= *(o - width); *(t++)= *(t - 3 * width); *(t++)= *(t - 3 * width); *(t++)= *(t - 3 * width); } #undef VYP } template void gradient_2d_ten_0(F* in, G* out, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double mult) { F *i0, *i1; G *o; ptrdiff_t i, j; double s1, s2, d1, d2, gx, gy, ddy, ddx, sp; #define VYP \ RDVAL \ for(j= 1; j < width; j++) { \ s2= s1; \ d2= d1; \ INC \ RDVAL \ gx= (s1 - s2) / ddx; \ gy= (d1 + d2) / ddy; \ *(o++)= mult * gx * gx; \ *(o++)= mult * gx * gy; \ *(o++)= mult * gy * gy; \ } \ INC \ *(o++)= mult * gx * gx; \ *(o++)= mult * gx * gy; \ *(o++)= mult * gy * gy; o= out; sp= sqrt((dx * dx + dy * dy) / 2.0); ddx= 2.0 * dx / sp; ddy= 2.0 * dy / sp; i0= in; i1= i0 + width; for(i= 1; i < height; i++) { VYP } for(j= 0; j < width; j++) { *(o++)= *(o - 3 * width); *(o++)= *(o - 3 * width); *(o++)= *(o - 3 * width); } #undef INC #undef RDVAL #undef VYP } template void gradient_2d_vec_1(F* in, G* out, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double mult) { F *i0, *i1, *i2; G *o; ptrdiff_t i, j; double e1, e2, e3, g1, g2, g3, gx, gy, ddx, ddy, sp; #define COMP \ gx= (e3 - e1) / ddx; \ gy= (g1 + g2 + g3) / ddy; \ *(o++)= mult * gx; \ *(o++)= mult * gy; #define INC \ i0++; i1++; i2++; #define RDVAL \ e3= (double)*i0 + (double)*i1 + (double)*i2; \ g3= (double)*i2 - (double)*i0; #define CIRC \ e1= e2; e2= e3; g1= g2; g2= g3; #define LOC1 \ RDVAL \ INC \ e1= e3; g1= g3; e2= e3; g2= g3; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= sqrt((dx * dx + dy * dy) / 2.0); ddx= 6.0 * dx / sp; ddy= 6.0 * dy / sp; o= out; i0=in; i1= in; i2= in + width; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 i0= in; for(i= 2; i < height; i++) { LOC1 for(j= 2; j< width; j++) { LOC2 } LOC3 } i2= i1; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 #undef COMP #undef LOC1 #undef LOC2 #undef LOC3 } template void gradient_2d_abs_1(F* in, G* out, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double mult) { F *i0, *i1, *i2; G *o; ptrdiff_t i, j; double e1, e2, e3, g1, g2, g3, gx, gy, ddx, ddy, sp; #define COMP \ gx= (e3 - e1) / ddx; \ gy= (g1 + g2 + g3) / ddy; \ *(o++)= mult * sqrt(gx * gx + gy * gy); #define LOC1 \ RDVAL \ INC \ e1= e3; g1= g3; e2= e3; g2= g3; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= sqrt((dx * dx + dy * dy) / 2.0); ddx= 6.0 * dx / sp; ddy= 6.0 * dy / sp; o= out; i0=in; i1= in; i2= in + width; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 i0= in; for(i= 2; i < height; i++) { LOC1 for(j= 2; j< width; j++) { LOC2 } LOC3 } i2= i1; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 #undef COMP #undef LOC1 #undef LOC2 #undef LOC3 } template void gradient_2d_abs_vec_1(F* in, G* out, G* vec, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double mult) { F *i0, *i1, *i2; G *o; G *v; ptrdiff_t i, j; double e1, e2, e3, g1, g2, g3, gx, gy, ddx, ddy, sp; #define COMP \ gx= (e3 - e1) / ddx; \ gy= (g1 + g2 + g3) / ddy; \ *(v++)= mult * gx; \ *(v++)= mult * gy; \ *(o++)= mult * sqrt(gx * gx + gy * gy); #define LOC1 \ RDVAL \ INC \ e1= e3; g1= g3; e2= e3; g2= g3; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= sqrt((dx * dx + dy * dy) / 2.0); ddx= 6.0 * dx / sp; ddy= 6.0 * dy / sp; o= out; v= vec; i0=in; i1= in; i2= in + width; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 i0= in; for(i= 2; i < height; i++) { LOC1 for(j= 2; j< width; j++) { LOC2 } LOC3 } i2= i1; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 #undef COMP #undef LOC1 #undef LOC2 #undef LOC3 } template void gradient_2d_abs_ten_1(F* in, G* out, G* ten, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double mult) { F *i0, *i1, *i2; G *o, *t; ptrdiff_t i, j; double e1, e2, e3, g1, g2, g3, gx, gy, ddx, ddy, sp; #define COMP \ gx= (e3 - e1) / ddx; \ gy= (g1 + g2 + g3) / ddy; \ *(t++)= mult * gx * gx; \ *(t++)= mult * gx * gy; \ *(t++)= mult * gy * gy; \ *(o++)= mult * sqrt(gx * gx + gy * gy); #define LOC1 \ RDVAL \ INC \ e1= e3; g1= g3; e2= e3; g2= g3; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= sqrt((dx * dx + dy * dy) / 2.0); ddx= 6.0 * dx / sp; ddy= 6.0 * dy / sp; o= out; t= ten; i0=in; i1= in; i2= in + width; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 i0= in; for(i= 2; i < height; i++) { LOC1 for(j= 2; j< width; j++) { LOC2 } LOC3 } i2= i1; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 #undef COMP #undef LOC1 #undef LOC2 #undef LOC3 } template void gradient_2d_ten_1(F* in, G* out, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double mult) { F *i0, *i1, *i2; G *o; ptrdiff_t i, j; double e1, e2, e3, g1, g2, g3, gx, gy, ddx, ddy, sp; #define COMP \ gx= (e3 - e1) / ddx; \ gy= (g1 + g2 + g3) / ddy; \ *(o++)= mult * gx * gx; \ *(o++)= mult * gx * gy; \ *(o++)= mult * gy * gy; #define LOC1 \ RDVAL \ INC \ e1= e3; g1= g3; e2= e3; g2= g3; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= sqrt((dx * dx + dy * dy) / 2.0); ddx= 6.0 * dx / sp; ddy= 6.0 * dy / sp; o= out; i0=in; i1= in; i2= in + width; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 i0= in; for(i= 2; i < height; i++) { LOC1 for(j= 2; j< width; j++) { LOC2 } LOC3 } i2= i1; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 #undef COMP #undef INC #undef RDVAL #undef CIRC #undef LOC1 #undef LOC2 #undef LOC3 } template void Gradient2D(Image& I, Image& J, ngbhsiz siz= ngbh3, double mult= 1.0) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 2) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1) || (J.nVars!=2)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= 2 * step) if (siz == ngbh3) gradient_2d_vec_1(q, p, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), mult); else gradient_2d_vec_0(q, p, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), mult); } template void Gradient2DAbs(Image& I, Image& J, ngbhsiz siz= ngbh3, double mult= 1.0) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 2) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1) || (J.nVars!=1)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step) { if (siz == ngbh3) gradient_2d_abs_1(q, p, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), mult); else gradient_2d_abs_0(q, p, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), mult); } } template void Gradient2DAbsVec(Image& I, Image& J, Image& V, ngbhsiz siz= ngbh3, double mult= 1.0) { if (!I.data || !J.data || !V.data) throw Allocerr(); if ((I.nDim < 2) || (J.nDim != I.nDim) || (V.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1) || (J.nVars!=1) || (V.nVars!=2)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims) || !DimsEq(I.nDim,I.dims,V.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F* q= I.data; G* p= J.data; G* v= V.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step, v+= 2 * step) { if (siz == ngbh3) gradient_2d_abs_vec_1(q, p, v, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), mult); else gradient_2d_abs_vec_0(q, p, v, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), mult); } } template void Gradient2DAbsTen(Image& I, Image& J, Image& T, ngbhsiz siz= ngbh3, double mult= 1.0) { if (!I.data || !J.data || !T.data) throw Allocerr(); if ((I.nDim < 2) || (J.nDim != I.nDim) || (T.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1) || (J.nVars!=1) || (T.nVars!=3)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims) || !DimsEq(I.nDim,I.dims,T.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F* q= I.data; G* p= J.data; G* t= T.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step, t+= 3 * step) { if (siz == ngbh3) gradient_2d_abs_ten_1(q, p, t, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), mult); else gradient_2d_abs_ten_0(q, p, t, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), mult); } } template void Gradient2DTen(Image& I, Image& J, ngbhsiz siz= ngbh3, double mult= 1.0) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 2) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1) || (J.nVars!=3)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= 3 * step) { if (siz == ngbh3) gradient_2d_ten_1(q, p, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), mult); else gradient_2d_ten_0(q, p, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), mult); } } template void gradient_3d_vec_0(F* in, G* out, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, double mult) { F *i00, *i01, *i10, *i11; G *o; ptrdiff_t i, j, k, size; double s1, s2, dh1, dh2, dv1, dv2, gx, gy, gz, ddx, ddy, ddz, sp; #define RDVAL \ s1= (double)*i00 + (double)*i01 + (double)*i10 + (double)*i11; \ dh1= (double)*i00 + (double)*i01 - (double)*i10 - (double)*i11; \ dv1= (double)*i00 - (double)*i01 + (double)*i10 - (double)*i11; #define INC \ i00++; i01++; i10++; i11++; #define VYP \ RDVAL \ for(k= 1; k < width; k++) { \ s2= s1; \ dh2= dh1; \ dv2= dv1; \ INC \ RDVAL \ gx= (s1 - s2) / ddx; \ gy= (dh1 + dh2) / ddy; \ gz= (dv1 + dv2) / ddz; \ *(o++)= mult * gx; \ *(o++)= mult * gy; \ *(o++)= mult * gz; \ } \ INC \ *(o++)= mult * gx; \ *(o++)= mult * gy; \ *(o++)= mult * gz; size= width * height; o= out; sp= sqrt((dx * dx + dy * dy + dz * dz) / 3.0); ddx= 4 * dx / sp; ddy= 4 * dy / sp; ddz= 4 * dz / sp; i00=in; i10= in + width; i01= in + size; i11= i01 + width; for(i= 1; i < depth; i++) { for(j= 1; j < height; j++) { VYP } for(j= 0; j < width; j++) *(o++)= *(o - 3 * width); i00+= width; i01+= width; i10+= width; i11+= width; } for(i= 0; i < size; i++) { *(o++)= *(o - 3 * size); *(o++)= *(o - 3 * size); *(o++)= *(o - 3 * size); } #undef VYP } template void gradient_3d_abs_0(F* in, G* out, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, double mult) { F *i00, *i01, *i10, *i11; G *o; ptrdiff_t i, j, k, size; double s1, s2, dh1, dh2, dv1, dv2, gx, gy, gz, ddx, ddy, ddz, sp; #define VYP \ RDVAL \ for(k= 1; k < width; k++) { \ s2= s1; \ dh2= dh1; \ dv2= dv1; \ INC \ RDVAL \ gx= (s1 - s2) / ddx; \ gy= (dh1 + dh2) / ddy; \ gz= (dv1 + dv2) / ddz; \ *(o++)= mult * sqrt(gx * gx + gy * gy + gz * gz); \ } \ INC \ *(o++)= mult * sqrt(gx * gx + gy * gy + gz * gz); size= width * height; o= out; sp= sqrt((dx * dx + dy * dy + dz * dz) / 3.0); ddx= 4 * dx / sp; ddy= 4 * dy / sp; ddz= 4 * dz / sp; i00=in; i10= in + width; i01= in + size; i11= i01 + width; for(i= 1; i < depth; i++) { for(j= 1; j < height; j++) { VYP } for(j= 0; j < width; j++) { *(o++)= *(o - width); } i00+= width; i01+= width; i10+= width; i11+= width; } for(i= 0; i < size; i++) *(o++)= *(o - size); #undef VYP } template void gradient_3d_abs_vec_0(F* in, G* out, G* vec, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, double mult) { F *i00, *i01, *i10, *i11; G *o, *v; ptrdiff_t i, j, k, size; double s1, s2, dh1, dh2, dv1, dv2, gx, gy, gz, ddx, ddy, ddz, sp; #define VYP \ RDVAL \ for(k= 1; k < width; k++) { \ s2= s1; \ dh2= dh1; \ dv2= dv1; \ INC \ RDVAL \ gx= (s1 - s2) / ddx; \ gy= (dh1 + dh2) / ddy; \ gz= (dv1 + dv2) / ddz; \ *(v++)= mult * gx; \ *(v++)= mult * gy; \ *(v++)= mult * gz; \ *(o++)= mult * sqrt(gx * gx + gy * gy + gz * gz); \ } \ INC \ *(v++)= mult * gx; \ *(v++)= mult * gy; \ *(v++)= mult * gz; \ *(o++)= mult * sqrt(gx * gx + gy * gy + gz * gz); size= width * height; o= out; v= vec; sp= sqrt((dx * dx + dy * dy + dz * dz) / 3.0); ddx= 4 * dx / sp; ddy= 4 * dy / sp; ddz= 4 * dz / sp; i00=in; i10= in + width; i01= in + size; i11= i01 + width; for(i= 1; i < depth; i++) { for(j= 1; j < height; j++) { VYP } for(j= 0; j < width; j++) { *(o++)= *(o - width); *(v++)= *(v - 3 * width); *(v++)= *(v - 3 * width); *(v++)= *(v - 3 * width); } i00+= width; i01+= width; i10+= width; i11+= width; } for(i= 0; i < size; i++) { *(o++)= *(o - size); *(v++)= *(v - 3 * size); *(v++)= *(v - 3 * size); *(v++)= *(v - 3 * size); } #undef VYP } template void gradient_3d_abs_ten_0(F* in, G* out, G* ten, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, double mult) { F *i00, *i01, *i10, *i11; G *o, *t; ptrdiff_t i, j, k, size; double s1, s2, dh1, dh2, dv1, dv2, gx, gy, gz, ddx, ddy, ddz, sp; #define VYP \ RDVAL \ for(k= 1; k < width; k++) { \ s2= s1; \ dh2= dh1; \ dv2= dv1; \ INC \ RDVAL \ gx= (s1 - s2) / ddx; \ gy= (dh1 + dh2) / ddy; \ gz= (dv1 + dv2) / ddz; \ *(t++)= mult * gx * gx; \ *(t++)= mult * gx * gy; \ *(t++)= mult * gy * gy; \ *(t++)= mult * gx * gz; \ *(t++)= mult * gy * gz; \ *(t++)= mult * gz * gz; \ *(o++)= mult * sqrt(gx * gx + gy * gy + gz * gz); \ } \ INC \ *(t++)= mult * gx * gx; \ *(t++)= mult * gx * gy; \ *(t++)= mult * gy * gy; \ *(t++)= mult * gx * gz; \ *(t++)= mult * gy * gz; \ *(t++)= mult * gz * gz; \ *(o++)= mult * sqrt(gx * gx + gy * gy + gz * gz); size= width * height; o= out; t= ten; sp= sqrt((dx * dx + dy * dy + dz * dz) / 3.0); ddx= 4 * dx / sp; ddy= 4 * dy / sp; ddz= 4 * dz / sp; i00=in; i10= in + width; i01= in + size; i11= i01 + width; for(i= 1; i < depth; i++) { for(j= 1; j < height; j++) { VYP } for(j= 0; j < width; j++) { *(t++)= *(t - width); *(t++)= *(t - width); *(t++)= *(t - width); *(t++)= *(t - width); *(t++)= *(t - width); *(t++)= *(t - width); *(o++)= *(o - width); } i00+= width; i01+= width; i10+= width; i11+= width; } for(i= 0; i < size; i++) { *(t++)= *(t - size); *(t++)= *(t - size); *(t++)= *(t - size); *(t++)= *(t - size); *(t++)= *(t - size); *(t++)= *(t - size); *(o++)= *(o - size); } #undef VYP } template void gradient_3d_ten_0(F* in, G* out, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, double mult) { F *i00, *i01, *i10, *i11; G *o; ptrdiff_t i, j, k, size; double s1, s2, dh1, dh2, dv1, dv2, gx, gy, gz, ddx, ddy, ddz, sp; #define VYP \ RDVAL \ for(k= 1; k < width; k++) { \ s2= s1; \ dh2= dh1; \ dv2= dv1; \ INC \ RDVAL \ gx= (s1 - s2) / ddx; \ gy= (dh1 + dh2) / ddy; \ gz= (dv1 + dv2) / ddz; \ *(o++)= mult * gx * gx; \ *(o++)= mult * gx * gy; \ *(o++)= mult * gy * gy; \ *(o++)= mult * gx * gz; \ *(o++)= mult * gy * gz; \ *(o++)= mult * gz * gz; \ } \ INC \ *(o++)= mult * gx * gx; \ *(o++)= mult * gx * gy; \ *(o++)= mult * gy * gy; \ *(o++)= mult * gx * gz; \ *(o++)= mult * gy * gz; \ *(o++)= mult * gz * gz; size= width * height; o= out; sp= sqrt((dx * dx + dy * dy + dz * dz) / 3.0); ddx= 4 * dx / sp; ddy= 4 * dy / sp; ddz= 4 * dz / sp; i00=in; i10= in + width; i01= in + size; i11= i01 + width; for(i= 1; i < depth; i++) { for(j= 1; j < height; j++) { VYP } for(j= 0; j < width; j++) { *(o++)= *(o - width); *(o++)= *(o - width); *(o++)= *(o - width); *(o++)= *(o - width); *(o++)= *(o - width); *(o++)= *(o - width); } i00+= width; i01+= width; i10+= width; i11+= width; } for(i= 0; i < size; i++) *(o++)= *(o - size); #undef VYP #undef INC #undef RDVAL } template void gradient_3d_vec_1(F* in, G* out, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, double mult) { F *i00, *i01, *i02, *i10, *i11, *i12, *i20, *i21, *i22; G *o; ptrdiff_t i, j, k, ssize; double h20, h22, dh2, dh1, dh0, dv2, dv1, dv0, t0, t1, t2, sp, ddx, ddy, ddz, gx, gy, gz; #define COMP \ gx= (t2 - t0) / ddx; \ gy= (dh0 + dh1 + dh2) / ddy; \ gz= (dv0 + dv1 + dv2) / ddz; \ *(o++)= mult * gx; \ *(o++)= mult * gy; \ *(o++)= mult * gz; #define INC \ i00++; i10++; i20++; \ i01++; i11++; i21++; \ i02++; i12++; i22++; #define RDVAL \ h20= (double)*i00 + (double)*i01 + (double)*i02; \ h22= (double)*i20 + (double)*i21 + (double)*i22; \ dv2= - (double)*i00 - (double)*i10 - (double)*i20 \ + (double)*i02 + (double)*i12 + (double)*i22; \ t2= h20 + h22 + \ (double)*i10 + (double)*i11 + (double)*i12; \ dh2= h22 - h20; #define CIRC \ dv0= dv1; dh0= dh1; t0= t1; \ dv1= dv2; dh1= dh2; t1= t2; #define LOC1 \ RDVAL \ INC \ dv0= dv2; dh0= dh2; t0= t2; \ dv1= dv2; dh1= dh2; t1= t2; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= sqrt((dx * dx + dy * dy + dz * dz) / 3.0); ddx= 18.0 * dx / sp; ddy= 18.0 * dy / sp; ddz= 18.0 * dz / sp; o= out; ssize= width * height; i00= in; i10= i00; i20= i00 + width; i01= in; i11= i01; i21= i01 + width; i02= in + ssize; i12= i02; i22= i02 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 for(i= 2; i < depth; i++) { i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i12= i11 + ssize; i02= i12; i22= i12 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 } i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i02= i01; i12= i11; i22= i21; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 #undef COMP #undef LOC1 #undef LOC2 #undef LOC3 } template void gradient_3d_abs_1(F* in, G* out, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, double mult) { F *i00, *i01, *i02, *i10, *i11, *i12, *i20, *i21, *i22; G *o; ptrdiff_t i, j, k, ssize; double h20, h22, dh2, dh1, dh0, dv2, dv1, dv0, t0, t1, t2, sp, ddx, ddy, ddz, gx, gy, gz; #define COMP \ gx= (t2 - t0) / ddx; \ gy= (dh0 + dh1 + dh2) / ddy; \ gz= (dv0 + dv1 + dv2) / ddz; \ *(o++)= mult * sqrt(gx * gx + gy * gy + gz * gz); #define LOC1 \ RDVAL \ INC \ dv0= dv2; dh0= dh2; t0= t2; \ dv1= dv2; dh1= dh2; t1= t2; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= sqrt((dx * dx + dy * dy + dz * dz) / 3.0); ddx= 18.0 * dx / sp; ddy= 18.0 * dy / sp; ddz= 18.0 * dz / sp; o= out; ssize= width * height; i00= in; i10= i00; i20= i00 + width; i01= in; i11= i01; i21= i01 + width; i02= in + ssize; i12= i02; i22= i02 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 for(i= 2; i < depth; i++) { i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i12= i11 + ssize; i02= i12; i22= i12 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 } i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i02= i01; i12= i11; i22= i21; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 #undef COMP #undef LOC1 #undef LOC2 #undef LOC3 } template void gradient_3d_abs_vec_1(F* in, G* out, G* vec, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, double mult) { F *i00, *i01, *i02, *i10, *i11, *i12, *i20, *i21, *i22; G *o, *v; ptrdiff_t i, j, k, ssize; double h20, h22, dh2, dh1, dh0, dv2, dv1, dv0, t0, t1, t2, sp, ddx, ddy, ddz, gx, gy, gz; #define COMP \ gx= (t2 - t0) / ddx; \ gy= (dh0 + dh1 + dh2) / ddy; \ gz= (dv0 + dv1 + dv2) / ddz; \ *(v++)= mult * gx; \ *(v++)= mult * gy; \ *(v++)= mult * gz; \ *(o++)= mult * sqrt(gx * gx + gy * gy + gz * gz); #define LOC1 \ RDVAL \ INC \ dv0= dv2; dh0= dh2; t0= t2; \ dv1= dv2; dh1= dh2; t1= t2; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= sqrt((dx * dx + dy * dy + dz * dz) / 3.0); ddx= 18.0 * dx / sp; ddy= 18.0 * dy / sp; ddz= 18.0 * dz / sp; o= out; v= vec; ssize= width * height; i00= in; i10= i00; i20= i00 + width; i01= in; i11= i01; i21= i01 + width; i02= in + ssize; i12= i02; i22= i02 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 for(i= 2; i < depth; i++) { i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i12= i11 + ssize; i02= i12; i22= i12 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 } i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i02= i01; i12= i11; i22= i21; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 #undef COMP #undef LOC1 #undef LOC2 #undef LOC3 } template void gradient_3d_abs_ten_1(F* in, G* out, G* ten, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, double mult) { F *i00, *i01, *i02, *i10, *i11, *i12, *i20, *i21, *i22; G *o, *t; ptrdiff_t i, j, k, ssize; double h20, h22, dh2, dh1, dh0, dv2, dv1, dv0, t0, t1, t2, sp, ddx, ddy, ddz, gx, gy, gz; #define COMP \ gx= (t2 - t0) / ddx; \ gy= (dh0 + dh1 + dh2) / ddy; \ gz= (dv0 + dv1 + dv2) / ddz; \ *(t++)= mult * gx * gx; \ *(t++)= mult * gx * gy; \ *(t++)= mult * gx * gz; \ *(t++)= mult * gy * gy; \ *(t++)= mult * gy * gz; \ *(t++)= mult * gz * gz; \ *(o++)= mult * sqrt(gx * gx + gy * gy + gz * gz); #define LOC1 \ RDVAL \ INC \ dv0= dv2; dh0= dh2; t0= t2; \ dv1= dv2; dh1= dh2; t1= t2; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= sqrt((dx * dx + dy * dy + dz * dz) / 3.0); ddx= 18.0 * dx / sp; ddy= 18.0 * dy / sp; ddz= 18.0 * dz / sp; o= out; t= ten; ssize= width * height; i00= in; i10= i00; i20= i00 + width; i01= in; i11= i01; i21= i01 + width; i02= in + ssize; i12= i02; i22= i02 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 for(i= 2; i < depth; i++) { i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i12= i11 + ssize; i02= i12; i22= i12 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 } i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i02= i01; i12= i11; i22= i21; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 #undef COMP #undef LOC1 #undef LOC2 #undef LOC3 } template void gradient_3d_ten_1(F* in, G* out, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, double mult) { F *i00, *i01, *i02, *i10, *i11, *i12, *i20, *i21, *i22; G *o; ptrdiff_t i, j, k, ssize; double h20, h22, dh2, dh1, dh0, dv2, dv1, dv0, t0, t1, t2, sp, ddx, ddy, ddz, gx, gy, gz; #define COMP \ gx= (t2 - t0) / ddx; \ gy= (dh0 + dh1 + dh2) / ddy; \ gz= (dv0 + dv1 + dv2) / ddz; \ *(o++)= mult * gx * gx; \ *(o++)= mult * gx * gy; \ *(o++)= mult * gx * gz; \ *(o++)= mult * gy * gy; \ *(o++)= mult * gy * gz; \ *(o++)= mult * gz * gz; #define LOC1 \ RDVAL \ INC \ dv0= dv2; dh0= dh2; t0= t2; \ dv1= dv2; dh1= dh2; t1= t2; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= sqrt((dx * dx + dy * dy + dz * dz) / 3.0); ddx= 18.0 * dx / sp; ddy= 18.0 * dy / sp; ddz= 18.0 * dz / sp; o= out; ssize= width * height; i00= in; i10= i00; i20= i00 + width; i01= in; i11= i01; i21= i01 + width; i02= in + ssize; i12= i02; i22= i02 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 for(i= 2; i < depth; i++) { i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i12= i11 + ssize; i02= i12; i22= i12 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 } i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i02= i01; i12= i11; i22= i21; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 #undef COMP #undef INC #undef RDVAL #undef CIRC #undef LOC1 #undef LOC2 #undef LOC3 } template void Gradient3D(Image& I, Image& J, ngbhsiz siz= ngbh3, double mult= 1.0) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1) || (J.nVars!=3)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= 3 * step) if (siz == ngbh3) gradient_3d_vec_1(q, p, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), mult); else gradient_3d_vec_0(q, p, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), mult); } template void Gradient3DAbs(Image& I, Image& J, ngbhsiz siz= ngbh3, double mult= 1.0) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1) || (J.nVars!=1)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step) if (siz == ngbh3) gradient_3d_abs_1(q, p, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), mult); else gradient_3d_abs_0(q, p, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), mult); } template void Gradient3DAbsVec(Image& I, Image& J, Image& V, ngbhsiz siz= ngbh3, double mult= 1.0) { if (!I.data || !J.data || !V.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim) || (V.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1) || (J.nVars!=1) || (V.nVars!=3)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims) || !DimsEq(I.nDim,I.dims,V.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F* q= I.data; G* p= J.data; G* v= V.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step, v+= 3 * step) if (siz == ngbh3) gradient_3d_abs_vec_1(q, p, v, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), mult); else gradient_3d_abs_vec_0(q, p, v, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), mult); } template void Gradient3DAbsTen(Image& I, Image& J, Image& T, ngbhsiz siz= ngbh3, double mult= 1.0) { if (!I.data || !J.data || !T.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim) || (T.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1) || (J.nVars!=1) || (T.nVars!=6)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims) || !DimsEq(I.nDim,I.dims,T.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F* q= I.data; G* p= J.data; G* t= T.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step, t+= 6 * step) if (siz == ngbh3) gradient_3d_abs_ten_1(q, p, t, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), mult); else gradient_3d_abs_ten_0(q, p, t, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), mult); } template void Gradient3DTen(Image& I, Image& J, ngbhsiz siz= ngbh3, double mult= 1.0) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1) || (J.nVars!=6)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= 6 * step) if (siz == ngbh3) gradient_3d_ten_1(q, p, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), mult); else gradient_3d_ten_0(q, p, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), mult); } template void curv_2d_max(F *in, G *out, ptrdiff_t width, ptrdiff_t height, double dx, double dy, int discrim, double mult) { F *i0, *i1, *i2; G *o; ptrdiff_t i, j; double e1, e2, e3, f1, f2, f3, g1, g2, g3, a, b, c, d, f, dxx, dyy, dxy, sp, crv; #define COMP \ d= 2.0 * (e1 + e2 + e3); \ a= (3.0 * (e1 + e3) - d) / dxx; \ c= (g3 - g1) / dxy; \ b= (3.0 * (f1 + f2 + f3) - d) / dyy; \ d= (a - b); \ d= sqrt(d * d + 4 * c * c); \ crv= a + b; \ if (discrim) { \ *(o++)= mult * ((crv < 0.0)?d:0.0); \ } \ else *(o++)= mult * 0.5 * (- crv + d); \ #define INC \ i0++; i1++; i2++; #define RDVAL \ e3= (double)*i0 + (double)*i1 + (double)*i2; \ f3= (double)*i0 + (double)*i2; \ g3= (double)*i0 - (double)*i2; #define CIRC \ e1= e2; e2= e3; f1= f2; f2= f3; g1= g2; g2= g3; #define LOC1 \ RDVAL \ INC \ e1= e3; f1= f3; g1= g3; e2= e3; f2= f3; g2= g3; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= (dx * dx + dy * dy) / 2.0; dxx= dx * dx * 3. / sp; dxy= dx * dy * 4. / sp; dyy= dy * dy * 3. / sp; o= out; i0=in; i1= in; i2= in + width; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 i0= in; for(i= 2; i < height; i++) { LOC1 for(j= 2; j< width; j++) { LOC2 } LOC3 } i2= i1; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 #undef LOC1 #undef LOC2 #undef LOC3 #undef COMP } template void curv_2d_max_vec(F *in, G *out, G *vec, ptrdiff_t width, ptrdiff_t height, double dx, double dy, int discrim, double mult) { F *i0, *i1, *i2; G *o, *t; ptrdiff_t i, j; double e1, e2, e3, f1, f2, f3, g1, g2, g3, a, b, c, d, e, f, dxx, dyy, dxy, sp, crv; #define COMP \ d= 2.0 * (e1 + e2 + e3); \ a= (3.0 * (e1 + e3) - d) / dxx; \ b= (3.0 * (f1 + f2 + f3) - d) / dyy; \ c= (g1 - g3) / dxy; \ d= (a - b); \ d= sqrt(d * d + 4 * c * c); \ f= (a + b); \ e= (f - d) / 2.0; \ *(o++)= discrim ? ((f < 0.) ? d : 0.0) : -mult * e; \ f= (f + d) / 2.0; \ e= a - e; \ d= c * c + e * e; \ if (d <= 0.0) { *(t++)= 0.0; *(t++)= 0.0; } \ else { \ d= f / sqrt(d); \ if (c < 0) { *(t++)= mult * -c * d; *(t++)= mult * e * d; } \ else { *(t++)= mult * c * d; *(t++)= mult * -e * d; } \ } #define LOC1 \ RDVAL \ INC \ e1= e3; f1= f3; g1= g3; e2= e3; f2= f3; g2= g3; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= (dx * dx + dy * dy) / 2.0; dxx= dx * dx * 3. / sp; dxy= dx * dy * 4. / sp; dyy= dy * dy * 3. / sp; o= out; t= vec; i0=in; i1= in; i2= in + width; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 i0= in; for(i= 2; i < height; i++) { LOC1 for(j= 2; j< width; j++) { LOC2 } LOC3 } i2= i1; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 #undef LOC1 #undef LOC2 #undef LOC3 #undef COMP } template void curv_2d_vec(F *in, G *vec, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double mult) { F *i0, *i1, *i2; G *t; ptrdiff_t i, j; double e1, e2, e3, f1, f2, f3, g1, g2, g3, a, b, c, d, e, f, dxx, dyy, dxy, sp; #define COMP \ d= 2.0 * (e1 + e2 + e3); \ a= (3.0 * (e1 + e3) - d) / dxx; \ b= (3.0 * (f1 + f2 + f3) - d) / dyy; \ c= (g1 - g3) / dxy; \ d= (a - b); \ d= sqrt(d * d + 4 * c * c); \ e= (a + b - d) / 2.0; \ f= (a + b + d) / 2.0; \ e= a - e; \ d= c * c + e * e; \ if (d <= 0.0) { *(t++)= 0.0; *(t++)= 0.0; } \ else { \ d= f / sqrt(d); \ if (c < 0) { *(t++)= mult * -c * d; *(t++)= mult * e * d; } \ else { *(t++)= mult * c * d; *(t++)= mult * -e * d; } \ } #define LOC1 \ RDVAL \ INC \ e1= e3; f1= f3; g1= g3; e2= e3; f2= f3; g2= g3; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= (dx * dx + dy * dy) / 2.0; dxx= dx * dx * 3. / sp; dxy= dx * dy * 4. / sp; dyy= dy * dy * 3. / sp; t= vec; i0=in; i1= in; i2= in + width; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 i0= in; for(i= 2; i < height; i++) { LOC1 for(j= 2; j< width; j++) { LOC2 } LOC3 } i2= i1; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 #undef COMP #undef LOC1 #undef LOC2 #undef LOC3 } template void curv_2d_max_ten(F *in, G *out, G *tens, ptrdiff_t width, ptrdiff_t height, double dx, double dy, int discrim, double mult) { F *i0, *i1, *i2; G *o, *t; ptrdiff_t i, j; double e1, e2, e3, f1, f2, f3, g1, g2, g3, a, b, c, d, f, dxx, dyy, dxy, sp, crv; #define COMP \ d= 2.0 * (e1 + e2 + e3); \ *(t++)= mult * (a= (3.0 * (e1 + e3) - d) / dxx); \ *(t++)= mult * (c= (g3 - g1) / dxy); \ *(t++)= mult * (b= (3.0 * (f1 + f2 + f3) - d) / dyy); \ d= (a - b); \ d= sqrt(d * d + 4 * c * c); \ crv= a + b; \ if (discrim) { \ *(o++)= mult * ((crv < 0.0)?d:0.0); \ } \ else *(o++)= mult * 0.5 * (- crv + d); \ #define LOC1 \ RDVAL \ INC \ e1= e3; f1= f3; g1= g3; e2= e3; f2= f3; g2= g3; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= (dx * dx + dy * dy) / 2.0; dxx= dx * dx * 3. / sp; dxy= dx * dy * 4. / sp; dyy= dy * dy * 3. / sp; o= out; t= tens; i0=in; i1= in; i2= in + width; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 i0= in; for(i= 2; i < height; i++) { LOC1 for(j= 2; j< width; j++) { LOC2 } LOC3 } i2= i1; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 #undef LOC1 #undef LOC2 #undef LOC3 #undef COMP } template void curv_2d_ten(F *in, G *tens, ptrdiff_t width, ptrdiff_t height, double dx, double dy, double mult) { F *i0, *i1, *i2; G *t; ptrdiff_t i, j; double e1, e2, e3, f1, f2, f3, g1, g2, g3, d, dxx, dyy, dxy, sp; #define COMP \ d= 2.0 * (e1 + e2 + e3); \ *(t++)= mult * (3.0 * (e1 + e3) - d) / dxx; \ *(t++)= mult * (g1 - g3) / dxy; \ *(t++)= mult * (3.0 * (f1 + f2 + f3) - d) / dyy; #define LOC1 \ RDVAL \ INC \ e1= e3; f1= f3; g1= g3; e2= e3; f2= f3; g2= g3; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= (dx * dx + dy * dy) / 2.0; dxx= dx * dx * 3. / sp; dxy= dx * dy * 4. / sp; dyy= dy * dy * 3. / sp; t= tens; i0=in; i1= in; i2= in + width; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 i0= in; for(i= 2; i < height; i++) { LOC1 for(j= 2; j< width; j++) { LOC2 } LOC3 } i2= i1; LOC1 for(j= 2; j < width; j++) { LOC2 } LOC3 #undef COMP #undef INC #undef RDVAL #undef CIRC #undef LOC1 #undef LOC2 #undef LOC3 } template void Curvature2DMax(Image& I, Image& J, int discr= 0, double mult= 1.0) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 2) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1) || (J.nVars!=1)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step) curv_2d_max(q, p, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), discr, mult); } template void Curvature2DMaxTen(Image& I, Image& J, Image& T, int discr= 0, double mult= 1.0) { if (!I.data || !J.data || !T.data) throw Allocerr(); if ((I.nDim < 2) || (J.nDim != I.nDim) || (T.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)||(T.nVars!=3)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)||!DimsEq(I.nDim,I.dims,T.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F* q= I.data; G* p= J.data; G* t= T.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step, t+= 3 * step) curv_2d_max_ten(q, p, t, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), discr, mult); } template void Curvature2DVec(Image& I, Image& T, double mult= 1.0) { if (!I.data || !T.data) throw Allocerr(); if ((I.nDim < 2) || (T.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1)||(T.nVars!=2)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,T.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F* q= I.data; G* t= T.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, t+= 2 * step) curv_2d_vec(q, t, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), mult); } template void Curvature2DMaxVec(Image& I, Image& J, Image& T, int discr= 0, double mult= 1.0) { if (!I.data || !J.data || !T.data) throw Allocerr(); if ((I.nDim < 2) || (J.nDim != I.nDim) || (T.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)||(T.nVars!=2)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)||!DimsEq(I.nDim,I.dims,T.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F* q= I.data; G* p= J.data; G* t= T.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step, t+= 2 * step) curv_2d_max_vec(q, p, t, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), discr, mult); } template void Curvature2DTen(Image& I, Image& T, double mult= 1.0) { if (!I.data || !T.data) throw Allocerr(); if ((I.nDim < 2) || (T.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1)||(T.nVars!=3)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,T.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F* q= I.data; G* t= T.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, t+= 3 * step) curv_2d_ten(q, t, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), mult); } template void curv_3d_max(F *in, G *out, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, int discrim, double mult) { F *i00, *i01, *i02, *i10, *i11, *i12, *i20, *i21, *i22; G *o; ptrdiff_t i, j, k, ssize; double h00, h10, h20, v00, v10, v20, h02, h12, h22, v02, v12, v22, t0, t1, t2, a0, a1, a2, sp, fp, dxx, dyy, dxy, dxz, dzz, dyz, ddxx, ddyy, ddxy, ddxz, ddzz, ddyz, b, c, d, p, q, r, s, fi3, sqrt3, b3, cf3, s3sf3; #define COMP \ fp= 2.0 * (t0 + t1 + t2); \ ddxx= (3.0 * (t0 + t2) - fp) / dxx; \ ddyy= (3.0 * (h00 + h10 + h20 + h02 + h12 + h22) - fp) / dyy; \ ddzz= (3.0 * (v00 + v10 + v20 + v02 + v12 + v22) - fp) / dzz; \ ddxy= (h22 - h20 - h02 + h00) / dxy; \ ddxz= (v22 - v20 - v02 + v00) / dxz; \ ddyz= (a0 + a1 + a2) / dyz; \ b= - ddxx - ddyy - ddzz; \ c= ddxx * ddyy + ddxx * ddzz + ddyy * ddzz \ - ddxy * ddxy - ddxz * ddxz - ddyz * ddyz; \ d= - 2.0 * ddxy * ddxz * ddyz - ddxx * ddyy * ddzz \ + ddxx * ddyz * ddyz + ddyy * ddxz * ddxz + ddzz * ddxy * ddxy; \ p= c - b * b / 3.0; \ if (p >= 0.0) { \ *(o++)= 0.0; \ } \ else { \ q= d - b * c / 3.0 + 2.0 * b * b * b / 27.0; \ r= sqrt(- p / 3.0); \ s= - 0.5 * q / (r * r * r); \ if (s <= -1.0) fi3= M_PI / 3.0; \ else if (s >= 1.0) fi3= 0.0; \ else fi3= acos(s) / 3.0; \ b3= b / 3.0; \ cf3= cos(fi3); \ s3sf3= sqrt3 * sin(fi3); \ if (discrim) { \ *(o++)= (b > 0.)? (mult * r *(3.* cf3 - s3sf3)) : 0.; \ } \ else *(o++)= mult * (r * (cf3 + s3sf3) - b3); \ } #define INC \ i00++; i10++; i20++; \ i01++; i11++; i21++; \ i02++; i12++; i22++; #define RDVAL \ h20= (double)*i00 + (double)*i01 + (double)*i02; \ h22= (double)*i20 + (double)*i21 + (double)*i22; \ v20= (double)*i00 + (double)*i10 + (double)*i20; \ v22= (double)*i02 + (double)*i12 + (double)*i22; \ t2= h20 + h22 + \ (double)*i10 + (double)*i11 + (double)*i12; \ a2= (double)*i00 - (double)*i02 \ - (double)*i20 + (double)*i22; #define CIRC \ h00= h10; h02= h12; v00= v10; v02= v12; t0= t1; a0= a1; \ h10= h20; h12= h22; v10= v20; v12= v22; t1= t2; a1= a2; #define LOC1 \ RDVAL \ INC \ h00= h20; h02= h22; v00= v20; v02= v22; t0= t2; a0= a2; \ h10= h20; h12= h22; v10= v20; v12= v22; t1= t2; a1= a2; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sqrt3= sqrt(3.0); sp= (dx * dx + dy * dy + dz * dz) / 3.0; dxx= dx * dx * 9. / sp; dyy= dy * dy * 9. / sp; dzz= dz * dz * 9. / sp; dxy= dx * dy * 12. / sp; dxz= dx * dz * 12. / sp; dyz= dy * dz * 12. / sp; o= out; ssize= width * height; i00= in; i10= i00; i20= i00 + width; i01= in; i11= i01; i21= i01 + width; i02= in + ssize; i12= i02; i22= i02 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 for(i= 2; i < depth; i++) { i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i12= i11 + ssize; i02= i12; i22= i12 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 } i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i02= i01; i12= i11; i22= i21; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 #undef COMP #undef LOC1 #undef LOC2 #undef LOC3 } template void curv_3d_max_ten(F *in, G *out, G *tens, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, int discrim, double mult) { F *i00, *i01, *i02, *i10, *i11, *i12, *i20, *i21, *i22; G *o, *t; ptrdiff_t i, j, k, ssize; double h00, h10, h20, v00, v10, v20, h02, h12, h22, v02, v12, v22, t0, t1, t2, a0, a1, a2, sp, fp, dxx, dyy, dxy, dxz, dzz, dyz, ddxx, ddyy, ddxy, ddxz, ddzz, ddyz, b, c, d, p, q, r, s, fi3, sqrt3, b3, cf3, s3sf3, crv, dcrv; #define COMP \ fp= 2.0 * (t0 + t1 + t2); \ ddxx= (3.0 * (t0 + t2) - fp) / dxx; \ ddyy= (3.0 * (h00 + h10 + h20 + h02 + h12 + h22) - fp) / dyy; \ ddzz= (3.0 * (v00 + v10 + v20 + v02 + v12 + v22) - fp) / dzz; \ ddxy= (h22 - h20 - h02 + h00) / dxy; \ ddxz= (v22 - v20 - v02 + v00) / dxz; \ ddyz= (a0 + a1 + a2) / dyz; \ *(t++)= mult * ddxx; \ *(t++)= mult * ddxy; \ *(t++)= mult * ddxz; \ *(t++)= mult * ddyy; \ *(t++)= mult * ddyz; \ *(t++)= mult * ddzz; \ b= - ddxx - ddyy - ddzz; \ c= ddxx * ddyy + ddxx * ddzz + ddyy * ddzz \ - ddxy * ddxy - ddxz * ddxz - ddyz * ddyz; \ d= - 2.0 * ddxy * ddxz * ddyz - ddxx * ddyy * ddzz \ + ddxx * ddyz * ddyz + ddyy * ddxz * ddxz + ddzz * ddxy * ddxy; \ p= c - b * b / 3.0; \ if (p >= 0.0) { \ *(o++)= 0.0; \ } \ else { \ q= d - b * c / 3.0 + 2.0 * b * b * b / 27.0; \ r= sqrt(- p / 3.0); \ s= - 0.5 * q / (r * r * r); \ if (s <= -1.0) fi3= M_PI / 3.0; \ else if (s >= 1.0) fi3= 0.0; \ else fi3= acos(s) / 3.0; \ b3= b / 3.0; \ cf3= cos(fi3); \ s3sf3= sqrt3 * sin(fi3); \ if (discrim) { \ *(o++)= (b > 0.)? (mult * r *(3.* cf3 - s3sf3)) : 0.; \ } \ else *(o++)= mult * (r * (cf3 + s3sf3) - b3); \ } #define LOC1 \ RDVAL \ INC \ h00= h20; h02= h22; v00= v20; v02= v22; t0= t2; a0= a2; \ h10= h20; h12= h22; v10= v20; v12= v22; t1= t2; a1= a2; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sqrt3= sqrt(3.0); sp= (dx * dx + dy * dy + dz * dz) / 3.0; dxx= dx * dx * 9. / sp; dyy= dy * dy * 9. / sp; dzz= dz * dz * 9. / sp; dxy= dx * dy * 12. / sp; dxz= dx * dz * 12. / sp; dyz= dy * dz * 12. / sp; o= out; t= tens; ssize= width * height; i00= in; i10= i00; i20= i00 + width; i01= in; i11= i01; i21= i01 + width; i02= in + ssize; i12= i02; i22= i02 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 for(i= 2; i < depth; i++) { i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i12= i11 + ssize; i02= i12; i22= i12 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 } i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i02= i01; i12= i11; i22= i21; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 #undef COMP #undef LOC1 #undef LOC2 #undef LOC3 } template void curv_3d_ten(F *in, G *out, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, int discrim, double mult) { F *i00, *i01, *i02, *i10, *i11, *i12, *i20, *i21, *i22; G *o; ptrdiff_t i, j, k, ssize; double h00, h10, h20, v00, v10, v20, h02, h12, h22, v02, v12, v22, t0, t1, t2, a0, a1, a2, sp, fp, dxx, dyy, dxy, dxz, dzz, dyz, ddxx, ddyy, ddxy, ddxz, ddzz, ddyz; #define COMP \ fp= 2.0 * (t0 + t1 + t2); \ ddxx= (3.0 * (t0 + t2) - fp) / dxx; \ ddyy= (3.0 * (h00 + h10 + h20 + h02 + h12 + h22) - fp) / dyy; \ ddzz= (3.0 * (v00 + v10 + v20 + v02 + v12 + v22) - fp) / dzz; \ ddxy= (h22 - h20 - h02 + h00) / dxy; \ ddxz= (v22 - v20 - v02 + v00) / dxz; \ ddyz= (a0 + a1 + a2) / dyz; \ *(o++)= mult * ddxx; \ *(o++)= mult * ddxy; \ *(o++)= mult * ddxz; \ *(o++)= mult * ddyy; \ *(o++)= mult * ddyz; \ *(o++)= mult * ddzz; #define LOC1 \ RDVAL \ INC \ h00= h20; h02= h22; v00= v20; v02= v22; t0= t2; a0= a2; \ h10= h20; h12= h22; v10= v20; v12= v22; t1= t2; a1= a2; \ RDVAL \ INC \ COMP #define LOC2 \ CIRC \ RDVAL \ INC \ COMP #define LOC3 \ CIRC \ COMP sp= (dx * dx + dy * dy + dz * dz) / 3.0; dxx= dx * dx * 9. / sp; dyy= dy * dy * 9. / sp; dzz= dz * dz * 9. / sp; dxy= dx * dy * 12. / sp; dxz= dx * dz * 12. / sp; dyz= dy * dz * 12. / sp; o= out; ssize= width * height; i00= in; i10= i00; i20= i00 + width; i01= in; i11= i01; i21= i01 + width; i02= in + ssize; i12= i02; i22= i02 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 for(i= 2; i < depth; i++) { i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i12= i11 + ssize; i02= i12; i22= i12 + width; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 } i10= i11 - ssize; i00= i10; i20= i10 + width; i01= i11; i21= i11 + width; i02= i01; i12= i11; i22= i21; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 i00= i10 - width; i01= i11 - width; i02= i12 - width; for(j= 2; j < height; j++) { LOC1 for(k= 2; k< width; k++) { LOC2 } LOC3 } i20= i10; i21= i11; i22= i12; LOC1 for(k= 2; k < width; k++) { LOC2 } LOC3 #undef COMP #undef INC #undef RDVAL #undef CIRC #undef LOC1 #undef LOC2 #undef LOC3 } template void Curvature3DMax(Image& I, Image& J, int discr= 0, double mult= 1.0) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step) curv_3d_max(q, p, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), discr, mult); } template void Curvature3DMaxTen(Image& I, Image& J, Image& T, int discr= 0, double mult= 1.0) { if (!I.data || !J.data || !T.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim) || (T.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=1)||(T.nVars!=6)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)||!DimsEq(I.nDim,I.dims,T.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F* q= I.data; G* p= J.data; G* t= T.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= step, t+= 6 * step) curv_3d_max_ten(q, p, t, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), discr, mult); } template void Curvature3DTen(Image& I, Image& J, int discr= 0, double mult= 1.0) { if (!I.data || !J.data) throw Allocerr(); if ((I.nDim < 3) || (J.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1)||(J.nVars!=6)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,J.dims)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; F* q= I.data; G* p= J.data; ptrdiff_t i; for (i= 0; i < numslic; i++, q+= step, p+= 6 * step) curv_3d_ten(q, p, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), discr, mult); } template void gauss_2d_ten_4(F *in, F *out, G *tens, ptrdiff_t width, ptrdiff_t height, double dx, double dy) { F *i0, *i1, *i2, *o; double s2, s3, sp; ptrdiff_t i, j; G *t; double a11, a22, isum; #define VYP4 \ sp= *i1; \ s2= (double)*i0 + (double)*i2; \ i0++; i1++; i2++; \ a11= *(t++); t++; a22= *(t++); \ *(o++)= (a22 * s2 + sp + a11 * (sp + (double)*i0)) / (1.0 + 2.0 * (a11 + a22)); \ for(j= 2; j < width; j++) { \ s3= sp; \ sp= *i1; \ s2= (double)*i0 + (double)*i2; \ i0++; i1++; i2++; \ a11= *(t++); t++; a22= *(t++); \ *(o++)= (a22 * s2 + sp + a11 * (s3 + (double)*i0)) / (1.0 + 2.0 * (a11 + a22)); \ } \ s3= sp; \ sp= *i1; \ s2= (double)*i0 + (double)*i2; \ i0++; i1++; i2++; \ a11= *(t++); t++; a22= *(t++); \ *(o++)= (a22 * s2 + sp + a11 * (s3 + sp)) / (1.0 + 2.0 * (a11 + a22)); o= out; i0= in; i2= in; i1= in + width; t= tens; VYP4 i2= in; for(i= 2; i < height; i++) { VYP4 } i1= i0; VYP4 } #undef VYP4 template void Gauss2DTen (Image& I, Image& T, int num) { if (!I.data || !T.data) throw Allocerr(); if ((I.nDim < 2) || (T.nDim != I.nDim)) throw Dimserr(); if ((I.nVars!=1) || (T.nVars!=3)) throw NVarerr(); if (!DimsEq(I.nDim,I.dims,T.dims)) throw Sizeerr(); if (num < 1) return; ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; F* q= I.data; G* t= T.data; F* pdat= new F[step]; ptrdiff_t i, j; for (i= 0; i < numslic; i++) { for (j= 0; j < num; j++) { memcpy(pdat, q, step * sizeof(F)); gauss_2d_ten_4(pdat, q, t, I.dims[0], I.dims[1], 1, 1); } q+= step; t+= 3 * step; } delete [] pdat; } template void exp_2d_ten_4(G *tens, ptrdiff_t width, ptrdiff_t height, double coef, int num) { ptrdiff_t i, j, ndat; G *t; double a11, a12, a22, b11, b12, b22, c11, c12, c22, pom, qom, com; ndat= width * height; t= tens; for(i= 0; i < ndat; i++) { a11= *t; a12= *(t+1); a22= *(t+2); b11= c11= 1.0; b12= c12= 0.0; b22= c22= 1.0; com= coef; for (j= 0; j < num; j++) { pom= b11 * a11 + b12 * a12; qom= b11 * a12 + b12 * a22; b11= pom; b22= b12 * a12 + b22 * a22; b12= qom; c11+= com * b11; c12+= com * b12; c22+= com * b22; com*= coef / (j+2); } *(t++)= c11; *(t++)= c12; *(t++)= c22; } } template void Exp2DTen (Image& T, double coeff, int num) { if (!T.data) throw Allocerr(); if (T.nDim < 2) throw Dimserr(); if (T.nVars!=3) throw NVarerr(); ptrdiff_t numslic= DimsProd(T.nDim - 2, T.dims + 2); ptrdiff_t step= T.dims[0] * T.dims[1]; G* t= T.data; ptrdiff_t i; for (i= 0; i < numslic; i++) { exp_2d_ten_4(t, T.dims[0], T.dims[1], coeff, num); t+= 3 * step; } } template void laplacian2d(F* in, ptrdiff_t width, ptrdiff_t height, double dx, double dy, F* out) { F *i0, *i1, *i2, *o; ptrdiff_t i, j; double k00, k01, k10, k11, s1, s2, s3, sp; /* kernel */ sp= (dx * dx + dy * dy) / 2.0; k00= - 4.0 / 3.0 * (1.0 / (dx * dx) + 1.0 / (dy * dy)) * sp; k01= (2.0 / (dy * dy) - 1.0 / (dx * dx) )/ 3.0 * sp; k10= (2.0 / (dx * dx) - 1.0 / (dy * dy) )/ 3.0 * sp; k11= (1.0 / (dy * dy) + 1.0 / (dx * dx) )/ 6.0 * sp; /* lokalni vypocet */ #define LOC \ s3= sp; \ sp= s1; \ s2= k00 * *(i0++) \ + k01 * (*(i1++) + *(i2++)); \ s1= k10 * *i0 \ + k11 * (*i1 + *i2); \ *(o++)= s1 + s2 + s3; o= out + width; i0=in + width; i2= in; i1= in + 2*width; for(i= 2; i < height; i++) { sp= k10 * *(i0++) + k11 * (*(i1++) + *(i2++)); s1= k10 * *i0 + k11 * (*i1 + *i2); o++; for(j= 2; j< width; j++) { LOC } i0++; i1++; i2++; o++; } o= out + width; for(i= 2; i < height; i++) { *o= *(o + 1); *(o + width - 1) = *(o + width - 2); o+= width; } memcpy(out, out + width, width * sizeof(F)); memcpy(out + (height - 1) * width, out + (height - 2) * width, width * sizeof(F)); #undef LOC } template void laplacian3d(F* in, ptrdiff_t width, ptrdiff_t height, ptrdiff_t depth, double dx, double dy, double dz, F* out) { F *i00, *i01, *i02, *i10, *i11, *i12, *i20, *i21, *i22, *o, *op; ptrdiff_t i, j, k, size; double k000, k001, k010, k100, k011, k101, k110, k111, s1, s2, s3, sp, dx2, dy2, dz2; size= width * height; dx2= dx * dx; dy2= dy * dy; dz2= dz * dz; /* kernel */ sp= (dx2 + dy2 + dz2) / 3.0; k000= - 2.0 * (1.0 / dx2 + 1.0 / dy2 + 1.0 / dz2) * sp / 9.0; k100= (1.0 / dx2 - 2.0 * (1.0 / dy2 + 1.0 / dz2)) * sp / 9.0; k010= (1.0 / dy2 - 2.0 * (1.0 / dx2 + 1.0 / dz2)) * sp / 9.0; k001= (1.0 / dz2 - 2.0 * (1.0 / dx2 + 1.0 / dy2)) * sp / 9.0; k110= (1.0 / dx2 + 1.0 / dy2 - 2.0 / dz2) * sp / 9.0; k101= (1.0 / dx2 + 1.0 / dz2 - 2.0 / dy2) * sp / 9.0; k011= (1.0 / dy2 + 1.0 / dz2 - 2.0 / dx2) * sp / 9.0; k111= (1.0 / dx2 + 1.0 / dy2 + 1.0 / dz2) * sp / 9.0; /* lokalni vypocet */ #define LOC1 \ sp= k100 * *(i00++) \ + k101 * (*(i01++) + *(i02++)) \ + k110 * (*(i10++) + *(i20++)) \ + k111 * (*(i11++) + *(i12++) \ + *(i21++) + *(i22++)); \ s1= k100 * *i00 \ + k101 * (*i01 + *i02) \ + k110 * (*i10 + *i20) \ + k111 * (*i11 + *i12 \ + *i21 + *i22); \ o++; #define LOC2 \ s3= sp; \ sp= s1; \ s2= k000 * *(i00++) \ + k001 * (*(i01++) + *(i02++)) \ + k010 * (*(i10++) + *(i20++)) \ + k011 * (*(i11++) + *(i12++) \ + *(i21++) + *(i22++)); \ s1= k100 * *i00 \ + k101 * (*i01 + *i02) \ + k110 * (*i10 + *i20) \ + k111 * (*i11 + *i12 \ + *i21 + *i22); \ *(o++)= s1 + s2 + s3; #define LOC3 \ i00++; i01++; i02++; i10++; i20++; i11++; i12++; i21++; i22++; o++; #define VYP \ for(i= 2; i < height; i++) { \ LOC1 \ for(j= 2; j< width; j++) { \ LOC2 \ } \ LOC3; \ } \ i00+= 2 * width; i01+= 2 * width; i02+= 2 * width; \ i10+= 2 * width; i20+= 2 * width; i11+= 2 * width; \ i12+= 2 * width; i21+= 2 * width; i22+= 2 * width; \ o+= 2 * width; o= out + size + width; i00= in + size + width; i01= in + 2 * size + width; i02= in + width; i10= in + size + 2 * width; i11= in + 2 * size + 2 * width; i12= in + 2 * width; i20= in + size; i21= in + 2 * size; i22= in; for(k= 2; k < depth; k++) { VYP } op= out; for(k= 2; k < depth; k++) { op+= size; o= op + width; for(i= 2; i < height; i++) { *o= *(o + 1); *(o + width - 1) = *(o + width - 2); o+= width; } memcpy(op, op + width, width * sizeof(F)); memcpy(op + (height - 1) * width, op + (height - 2) * width, width * sizeof(F)); } memcpy(out, out + size, size * sizeof(F)); memcpy(out + (depth - 1) * size, out + (depth - 2) * size, size * sizeof(F)); #undef LOC1 #undef LOC2 #undef LOC3 #undef VYP } template void Laplace2D (Image& I) { ptrdiff_t i, j; F *q, *pdat; if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if ((I.dims[0]<3)||(I.dims[1]<3)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 2, I.dims + 2); ptrdiff_t step= I.dims[0] * I.dims[1]; q= I.data; pdat= new F[step]; for (i= 0; i < numslic; i++) { memset(pdat, 0, step * sizeof(F)); //temp memcpy(pdat, q, step * sizeof(F)); laplacian2d(pdat, I.dims[0], I.dims[1], I.Dx(0), I.Dx(1), q); q+= step; } delete [] pdat; } template void Laplace3D (Image& I) { ptrdiff_t i, j; F *q, *pdat; if (!I.data) throw Allocerr(); if (3 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); if ((I.dims[0]<3)||(I.dims[1]<3)||(I.dims[2]<3)) throw Sizeerr(); ptrdiff_t numslic= DimsProd(I.nDim - 3, I.dims + 3); ptrdiff_t step= I.dims[0] * I.dims[1] * I.dims[2]; q= I.data; pdat= new F[step]; for (i= 0; i < numslic; i++) { memcpy(pdat, q, step * sizeof(F)); laplacian3d(pdat, I.dims[0], I.dims[1], I.dims[2], I.Dx(0), I.Dx(1), I.Dx(2), q); q+= step; } delete [] pdat; } template void add_laplace(F* data, float* buf, ptrdiff_t* dims, int nDim, double dx, int dim) { ptrdiff_t nData = DimsProd(nDim, dims) / dims[dim]; ptrdiff_t nInter = DimsProd(dim, dims); ptrdiff_t nLine = dims[dim]; ptrdiff_t nStep = nInter * (nLine - 1); F *i0, *i1, *i2, *i3; float *o0, *o1; ptrdiff_t i, j, k, l, fi, n; double dx2 = dx * dx; i0 = data; o0 = buf; for (i = 0; i < nData; i += nInter) { for (k = 0; k < nInter; k++) { i1 = i0 + nInter; o1 = o0 + nInter; for (l = 2; l < nLine; l++, i1 += nInter, o1 += nInter) *o1 += (*(i1 - nInter) - 2. * *i1 + *(i1 + nInter)) / dx2; *o0 = *(o0 + nInter); *o1 = *(o1 - nInter); i0++; o0++; } i0 += nStep; o0 += nStep; } } template void Laplace(Image& I, Image& O, int ndim) { if ((!I.data) || (!O.data)) throw Allocerr(); if (O.nDim != I.nDim) throw Dimserr(); if ((I.nVars != 1) || (O.nVars != 1)) throw NVarerr(); if (!DimsEq(I.nDim, I.dims, O.dims)) throw Sizeerr(); if (ndim > I.nDim) throw Argerr(); O.SetData(); int i; for (i = 0; i < ndim; i++) add_laplace(I.data, O.data, I.dims, I.nDim, I.Dx(i), i); } template bool traceobj2d(F* data, ptrdiff_t width, ptrdiff_t height, ptrdiff_t j0, ptrdiff_t i0, int dir0, con2D con, ObjectArray& O){ ptrdiff_t i, j, i1, i2, i3, j1, j2, j3; int dir; i= i0; j= j0; dir= dir0; F val= data[i*width+j]; Object po(2); po[1]= i; po[0]= j; O.push_back(po); do { switch (dir) { case 0: i1= i+1; j1= j; i2= i1; j2= j-1; i3= i1; j3= j; break; // 1, 0 1,-1 case 1: i1= i; j1= j+1; i2= i+1; j2= j1; i3= i2; j3= j1; break; // 0, 1 1, 1 case 2: i1= i-1; j1= j; i2= i1; j2= j+1; i3= i; j3= j2; break; //-1, 0 -1, 1 case 3: i1= i; j1= j-1; i2= i-1; j2= j1; i3= i; j3= j; break; // 0,-1 -1,-1 } F val1, val2; if ((i1>=0)&&(i1=0)&&(j1=0)&&(i2=0)&&(j2 3) dir= 0; } } po[1]= i3; po[0]= j3; O.push_back(po); } while ((i!=i0)||(j!=j0)||(dir!=dir0)); return true; } template void TraceObjects2DBin(Binary& I, ObjectArrayArray& O, bool holes, bool at_bound, con2D con= con4) { if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); Img pim(I); size_t val= 1; Bin pib(I); std::vector vals; pim.SetData(); pib.SetData(I.data); if (at_bound) EraseBoundary2DBin(pib, con); Label2D(pib, pim, con, val); TraceObjects2D(pim, O, vals, 0, con); size_t nobj= val-1; if (holes) { pib.SetData(I.data); pib.SetData(IL_BU_NOT); EraseBoundary2DBin(pib, complement(con)); Label2D(pib, pim, complement(con), val); TraceObjects2D(pim, O, vals, nobj, complement(con)); } } template void TraceObjects2D(Image& I, ObjectArrayArray& O, std::vector& vals, F minp= 0, con2D con= con4) { if (!I.data) throw Allocerr(); if (2 > I.nDim) throw Dimserr(); if (I.nVars!=1) throw NVarerr(); ptrdiff_t width= I.dims[0]; ptrdiff_t height= I.dims[1]; std::set used; F *p= I.data; ptrdiff_t i, j; for(j= 0; j < height; j++) for(i= 0; i < width; i++, p++) if ((*p>minp) && (used.find(*p)==used.end())) { ObjectArray po; if (!traceobj2d(I.data, width, height, i, j, 0, con, po)) { throw Imgerr(); } O.push_back(po); vals.push_back(*p); used.insert(*p); } } #ifdef jil_redefine_min #define min(a,b) (((a)<(b))?(a):(b)) #endif #ifdef jil_redefine_max #define max(a,b) (((a)>(b))?(a):(b)) #endif #endif