void FreeDistortBaseFx::doDryCompute(TRectD &rect, double frame, const TRenderSettings &info)
{
	if (!m_input.isConnected())
		return;

	if (m_deactivate->getValue()) {
		m_input->dryCompute(rect, frame, info);
		return;
	}

	TRectD rectOnInput;
	TRenderSettings infoOnInput;
	TRectD inBBox;

	safeTransform(frame, 0, rect, info, rectOnInput, infoOnInput, inBBox);

	rectOnInput *= inBBox;

	if (!myIsEmpty(rectOnInput))
		m_input->dryCompute(rectOnInput, frame, infoOnInput);
}
Exemple #2
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { ALLOCATES();
  real     *X, XX[NN], Xk[NN], XXr[NN], D[N], DS[N], fD[N], V[NN], VS[NN], *O, Ok[NN];
  long     k1, K1, k2, K2, k3, K3, ii, jj;
  int      ORDER[N];
  char     STR[100];

  enum     symmetrize_ { NONE , X_Xt , Xt_X , PLUS };
  enum     symmetrize_ symmetrize;  
  
  enum     outs_types { ID , INVERSE , EIGVALS , EIGVECS , EIGVALSDIAG , MAXDIFF , SQRT , LOG , EXP , evalFUN , DET , TRACE };
  enum     outs_types outs[50];
  int      ndims, Odims[50];
  real     det;
  
  int      oid;
  int      D_computed, V_computed, D_sorted, V_sorted, ORDER_computed;
  int      dim1 , dim2;
  mxArray  *mxX;
  
  if( nlhs == 0 ){ nlhs = 1; }
  if( nlhs > nrhs-2 ){
    myErrMsgTxt("There are no enough inputs.\n");
  }

  if( mxIsCell( prhs[0] ) ){
    mxX = mxGetCell( prhs[0] , 0 );
    dim1 = myGetValue( mxGetCell( prhs[0] , 1 ) );
    dim2 = myGetValue( mxGetCell( prhs[0] , 2 ) );
  } else {
    mxX = prhs[0];
    dim1 = 1;
    dim2 = 2;
  }
  
  if( ( mySize( mxX , dim1-1 ) != N ) || ( mySize( mxX , dim1-1 ) != N ) ){
    myErrMsgTxt("size( X , %d ) and size( X , %d ) have to be equal to three.\n",dim1,dim2);
  }
  

  if( myIsEmpty( prhs[1] ) ){
    symmetrize = NONE;
  } else if( mxIsChar(prhs[1]) ){
    mxGetString( prhs[1], STR, 100 );
    
    if(        !myStrcmpi(STR,"+") ) {
      symmetrize = PLUS;
    } else if( !myStrcmpi(STR,"xt*x") || !myStrcmpi(STR,"xtx") ) {
      symmetrize = Xt_X;
    } else if( !myStrcmpi(STR,"x*xt") || !myStrcmpi(STR,"xxt") ) {
      symmetrize = X_Xt;
    } else {
      myErrMsgTxt("Second argument expected: 'xt*x' , 'x*xt' , '+' , or [].\n");
    }

  } else {
    myErrMsgTxt("Second argument expected: 'xt*x' , 'x*xt' , '+' , or [].\n");
  }
  

  for( oid = 0 ; oid < nlhs ; oid++ ){
    if( ! mxIsChar(prhs[oid+2]) ){
      myErrMsgTxt("Valids arguments are: 'id' 'eigval' 'eigvec' 'log' 'sqrt' 'exp' 'error'.\n");
    }
    mxGetString( prhs[oid+2], STR, 100 );
    
    if(        !myStrcmpi(STR,"id") ) {
      outs[oid] = ID;
    } else if( !myStrcmpi(STR,"inv") || !myStrcmpi(STR,"inverse") ) {
      outs[oid] = INVERSE;
    } else if( !myStrcmpi(STR,"det") ) {
      outs[oid] = DET;
    } else if( !myStrcmpi(STR,"trace") ) {
      outs[oid] = TRACE;
    } else if( !myStrcmpi(STR,"evec") || !myStrcmpi(STR,"v") || !myStrcmpi(STR,"eigenvec") || !myStrcmpi(STR,"eigvec") || !myStrcmpi(STR,"eigenvectors") ) {
      outs[oid] = EIGVECS;
    } else if( !myStrcmpi(STR,"eval") || !myStrcmpi(STR,"d") || !myStrcmpi(STR,"eigenval") || !myStrcmpi(STR,"eigval") || !myStrcmpi(STR,"eigenvalues") ) {
      outs[oid] = EIGVALS;
    } else if( !myStrcmpi(STR,"diag") || !myStrcmpi(STR,"dd") ) {
      outs[oid] = EIGVALSDIAG;
    } else if( !myStrcmpi(STR,"error") ) {
      outs[oid] = MAXDIFF;
    } else if( !myStrcmpi(STR,"sqrt") || !myStrcmpi(STR,"sqrtm") ) {
      outs[oid] = SQRT;
    } else if( !myStrcmpi(STR,"log") || !myStrcmpi(STR,"logm") ) {
      outs[oid] = LOG;
    } else if( !myStrcmpi(STR,"exp") || !myStrcmpi(STR,"expm") ) {
      outs[oid] = EXP;
    } else {
      myErrMsgTxt("Valids arguments are: 'id' 'inv' 'det' 'trace' 'eigval' 'eigvec' 'log' 'sqrt' 'exp' 'error'.\n");
    }
  }
  
  
  X = mxGetPr( mxX );
  ndims = myGetSizes( mxX , Odims );
  
  for( oid = 0 ; oid < nlhs ; oid++ ){
    switch( outs[oid] ){
      case ID:
        plhs[oid] = mxCreateNumericArray( ndims , Odims , mxREAL_CLASS , mxREAL );
        break;
      case INVERSE:
        plhs[oid] = mxCreateNumericArray( ndims , Odims , mxREAL_CLASS , mxREAL );
        break;
      case DET:
        Odims[dim1-1] = 1;
        Odims[dim2-1] = 1;
        plhs[oid] = mxCreateNumericArray( ndims , Odims , mxREAL_CLASS , mxREAL );        
        Odims[dim1-1] = N;
        Odims[dim2-1] = N;
        break;
      case TRACE:
        Odims[dim1-1] = 1;
        Odims[dim2-1] = 1;
        plhs[oid] = mxCreateNumericArray( ndims , Odims , mxREAL_CLASS , mxREAL );        
        Odims[dim1-1] = N;
        Odims[dim2-1] = N;
        break;
      case EIGVALS:
        Odims[dim2-1] = 1;
        plhs[oid] = mxCreateNumericArray( ndims , Odims , mxREAL_CLASS , mxREAL );
        Odims[dim2-1] = N;
        break;
      case EIGVECS:
        plhs[oid] = mxCreateNumericArray( ndims , Odims , mxREAL_CLASS , mxREAL );        
        break;
      case EIGVALSDIAG:
        plhs[oid] = mxCreateNumericArray( ndims , Odims , mxREAL_CLASS , mxREAL );        
        break;
      case MAXDIFF:
        Odims[dim1-1] = 1;
        Odims[dim2-1] = 1;
        plhs[oid] = mxCreateNumericArray( ndims , Odims , mxREAL_CLASS , mxREAL );        
        Odims[dim1-1] = N;
        Odims[dim2-1] = N;
        break;
      case EXP:
        plhs[oid] = mxCreateNumericArray( ndims , Odims , mxREAL_CLASS , mxREAL );        
        break;
      case LOG:
        plhs[oid] = mxCreateNumericArray( ndims , Odims , mxREAL_CLASS , mxREAL );        
        break;
      case SQRT:
        plhs[oid] = mxCreateNumericArray( ndims , Odims , mxREAL_CLASS , mxREAL );        
        break;
      case evalFUN:
        plhs[oid] = mxCreateNumericArray( ndims , Odims , mxREAL_CLASS , mxREAL );        
        break;
    }
  }
  
  K1 = 1;
  for( k1 = 0    ; k1 < dim1-1 ; k1++ ){  K1 *= Odims[k1]; }
  K2 = 1;
  for( k2 = dim1 ; k2 < dim2-1 ; k2++ ){  K2 *= Odims[k2]; }
  K3 = 1;
  for( k3 = dim2 ; k3 < ndims  ; k3++ ){  K3 *= Odims[k3]; }


  for( k3 = 0 ; k3 < K3 ; k3++ ){
  for( k2 = 0 ; k2 < K2 ; k2++ ){
  for( k1 = 0 ; k1 < K1 ; k1++ ){
    if( K1 == 1 && K2 == 1 ){
      memcpy( Xk , X + k3*NN , NN*sizeof( real ) );
    } else {
      for( jj = 0 ; jj < N ; jj++ ){ for( ii = 0 ; ii < N ; ii++ ){
        Xk[ ii + N*jj ] = X[  k1 + K1*( ii + N*( k2 + K2*( jj + N*k3 ))) ];
      } }
    }
    
    
    switch( symmetrize ){
      case NONE:
        memcpy( XX , Xk , NN*sizeof( real ) );
        break;

      case X_Xt:
        XX[0] = Xk[0]*Xk[0] + Xk[2]*Xk[2];
        XX[1] = Xk[1]*Xk[0] + Xk[3]*Xk[2];

        XX[2] = Xk[0]*Xk[1] + Xk[2]*Xk[3];
        XX[3] = Xk[1]*Xk[1] + Xk[3]*Xk[3];
        break;

      case Xt_X:
        XX[0] = Xk[0]*Xk[0] + Xk[1]*Xk[1];
        XX[1] = Xk[2]*Xk[0] + Xk[3]*Xk[1];

        XX[2] = Xk[0]*Xk[2] + Xk[1]*Xk[3];
        XX[3] = Xk[2]*Xk[2] + Xk[3]*Xk[3];
        break;

      case PLUS:
        XX[0]         = Xk[0];
        XX[1] = XX[2] = ( Xk[1] + Xk[2] )/2.0;
        XX[3]         = Xk[3];
        break;
    }
    
    D_computed      = 0;
    V_computed      = 0;
    ORDER_computed  = 0;
    D_sorted        = 0;
    V_sorted        = 0;
    
    for( oid = 0 ; oid < nlhs ; oid++ ){
      switch( outs[oid] ){
        case ID:
          memcpy( Ok , XX , NN*sizeof( real ) );
          
          O = mxGetPr( plhs[oid] );
          ToOutput2x2;
          break;
          
          
        case INVERSE:
          det = XX[0]*XX[3] - XX[1]*XX[2];
          det = 1.0/det;
          
          Ok[0] =  XX[3] *det;
          Ok[1] = -XX[1] *det;
          Ok[2] = -XX[2] *det;
          Ok[3] =  XX[0] *det;
          
          O = mxGetPr( plhs[oid] );
          ToOutput2x2;
          break;
          

        case DET:
          Ok[0] = XX[0]*XX[3] - XX[1]*XX[2];
          
          O = mxGetPr( plhs[oid] );
          ToOutput1x1;
          break;

          
        case TRACE:
          Ok[0] =  XX[0] + XX[3];
          
          O = mxGetPr( plhs[oid] );
          ToOutput1x1;
          break;

          
        case EIGVALS:
          if( !D_computed     ){ EigenValues2x2( XX , D );          D_computed = 1;      }
          if( !ORDER_computed ){ GetOrder( D, ORDER );              ORDER_computed = 1;  }
          if( !D_sorted       ){ SortEigenValues( D, ORDER , DS );  D_sorted = 1;        }
          
          memcpy( Ok , DS , N*sizeof( real ) );
          
          O = mxGetPr( plhs[oid] );
          ToOutput2x1;
          break;


        case EIGVALSDIAG:
          if( !D_computed     ){ EigenValues2x2( XX , D );          D_computed = 1;      }
          if( !ORDER_computed ){ GetOrder( D, ORDER );              ORDER_computed = 1;  }
          if( !D_sorted       ){ SortEigenValues( D, ORDER , DS );  D_sorted = 1;        }

          Ok[0] = DS[0];
          Ok[3] = DS[1];
          Ok[1] = Ok[2] = 0;

          O = mxGetPr( plhs[oid] );
          ToOutput2x2;
          break;

          
        case EIGVECS:
          if( !D_computed     ){ EigenValues2x2( XX , D );          D_computed = 1;      }
          if( !V_computed     ){ EigenVectors2x2( XX , D , V);      V_computed = 1;      }
          if( !ORDER_computed ){ GetOrder( D, ORDER );              ORDER_computed = 1;  }
          if( !V_sorted       ){ SortEigenVectors( V, ORDER , VS);  V_sorted = 1;        }

          memcpy( Ok , VS , NN*sizeof( real ) );
          
          O = mxGetPr( plhs[oid] );
          ToOutput2x2;
          break;


//         case MAXDIFF:
//           if( !D_computed     ){ EigenValuesSym3x3( XX , D );       D_computed = 1;      }
//           if( !V_computed     ){ EigenVectorsSym3x3( XX , D , V);   V_computed = 1;      }
// 
//           Ok[0] = V[0]*V[0]*D[0] + V[3]*V[3]*D[1] + V[6]*V[6]*D[2];
//           Ok[1] = V[1]*V[0]*D[0] + V[4]*V[3]*D[1] + V[7]*V[6]*D[2];
//           Ok[2] = V[2]*V[0]*D[0] + V[5]*V[3]*D[1] + V[8]*V[6]*D[2];
// 
//           Ok[3] = V[0]*V[1]*D[0] + V[3]*V[4]*D[1] + V[6]*V[7]*D[2];
//           Ok[4] = V[1]*V[1]*D[0] + V[4]*V[4]*D[1] + V[7]*V[7]*D[2];
//           Ok[5] = V[2]*V[1]*D[0] + V[5]*V[4]*D[1] + V[8]*V[7]*D[2];
// 
//           Ok[6] = V[0]*V[2]*D[0] + V[3]*V[5]*D[1] + V[6]*V[8]*D[2];
//           Ok[7] = V[1]*V[2]*D[0] + V[4]*V[5]*D[1] + V[7]*V[8]*D[2];
//           Ok[8] = V[2]*V[2]*D[0] + V[5]*V[5]*D[1] + V[8]*V[8]*D[2];
// 
//           Ok[0] =  MAX9( fabs( Ok[0] - XX[0] ) ,
//                          fabs( Ok[1] - XX[1] ) ,
//                          fabs( Ok[2] - XX[2] ) ,
//                          fabs( Ok[3] - XX[3] ) ,
//                          fabs( Ok[4] - XX[4] ) ,
//                          fabs( Ok[5] - XX[5] ) ,
//                          fabs( Ok[6] - XX[6] ) ,
//                          fabs( Ok[7] - XX[7] ) ,
//                          fabs( Ok[8] - XX[8] ) );
// 
//           O = mxGetPr( plhs[oid] );
//           ToOutput1x1;
//           break;
// 
//           
//         case SQRT:
//           if( !D_computed     ){ EigenValuesSym3x3( XX , D );       D_computed = 1;      }
//           if( !V_computed     ){ EigenVectorsSym3x3( XX , D , V);   V_computed = 1;      }
// 
//           fD[0] = sqrt( D[0] );
//           fD[1] = sqrt( D[1] );
//           fD[2] = sqrt( D[2] );
//           
//           FillOk;
//           O = mxGetPr( plhs[oid] );
//           ToOutput3x3;
//           break;
// 
//           
//         case LOG:
//           if( !D_computed     ){ EigenValuesSym3x3( XX , D );       D_computed = 1;      }
//           if( !V_computed     ){ EigenVectorsSym3x3( XX , D , V);   V_computed = 1;      }
// 
//           fD[0] = log( D[0] );
//           fD[1] = log( D[1] );
//           fD[2] = log( D[2] );
//           
//           FillOk;
//           O = mxGetPr( plhs[oid] );
//           ToOutput3x3;
//           break;

        #define r       eval[0]
        #define e       eval[1]
        #define er      eval[2]
        case EXP:
          r = XX[0] - XX[3];
          r = 4*XX[1]*XX[2] + r*r;
          
          if( r >= 0 ){
            r = sqrt(r);
            
            
            e = exp( ( XX[0] + XX[3] - r )/2 )/r/2.0;
            er = exp(r);
            
            Ok[0] = e * ( XX[3] - XX[0] + r + er*(XX[0]-XX[3]+r) );
            
            Ok[1] = e * XX[1] * ( er - 1 ) * 2;
            
            Ok[2] = e * XX[2] * ( er - 1 ) * 2;
            
            Ok[3] = e * ( XX[0] - XX[3] + r + er*(XX[3]-XX[0]+r) );

          } else {
            
            r = sqrt( -r );
            
            e = exp( ( XX[0] + XX[3] )/2 )/r;
            er = sin(r/2);
            
            Ok[0] = e * ( r*cos(r/2) + ( XX[0]-XX[3] )*er );
            
            Ok[1] = 2 * XX[1] * e * er;
            
            Ok[2] = 2 * XX[2] * e * er;            
            
            Ok[3] = e * ( r*cos(r/2) + ( XX[3]-XX[0] )*er );
            
          }
          
          
          O = mxGetPr( plhs[oid] );
          ToOutput2x2;
          break;

          
          
//         case evalFUN:
//           O = mxGetPr( plhs[oid] ) + k*NN;
//           if( !D_computed     ){ EigenValuesSym3x3( XX , D );       D_computed = 1;      }
//           if( !V_computed     ){ EigenVectorsSym3x3( XX , D , V);   V_computed = 1;      }
// 
//           fD[0] = exp( D[0] );
//           fD[1] = exp( D[1] );
//           fD[2] = exp( D[2] );
// 
//           mexCallMATLAB(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[], const char *name)
//           
//           FillO
//           break;
      
      }
    }
    
  }}}
  
  EXIT: myFreeALLOCATES();
}
void FreeDistortBaseFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri)
{
	if (!m_input.isConnected())
		return;

	//Upon deactivation, this fx does nothing.
	if (m_deactivate->getValue()) {
		m_input->compute(tile, frame, ri);
		return;
	}

	//Get the source quad
	TPointD p00_b = m_p00_b->getValue(frame);
	TPointD p10_b = m_p10_b->getValue(frame);
	TPointD p01_b = m_p01_b->getValue(frame);
	TPointD p11_b = m_p11_b->getValue(frame);

	//Get destination quad
	TPointD p00_a = m_p00_a->getValue(frame);
	TPointD p10_a = m_p10_a->getValue(frame);
	TPointD p01_a = m_p01_a->getValue(frame);
	TPointD p11_a = m_p11_a->getValue(frame);

	if (m_isCastShadow) {
		//Shadows are mirrored
		tswap(p00_a, p01_a);
		tswap(p10_a, p11_a);
	}

	//Get requested tile's geometry
	TRasterP tileRas(tile.getRaster());
	TRectD tileRect(convert(tileRas->getBounds()) + tile.m_pos);

	//Call transform to get the minimal rectOnInput
	TRectD inRect;
	TRenderSettings riNew;
	TRectD inBBox;

	safeTransform(frame, 0, tileRect, ri, inRect, riNew, inBBox);

	//Intersect with the bbox
	inRect *= inBBox;

	if (myIsEmpty(inRect))
		return;

	double scale = ri.m_affine.a11;

	double downBlur = m_downBlur->getValue(frame) * scale;
	double upBlur = m_upBlur->getValue(frame) * scale;
	int brad = tceil(tmax(downBlur, upBlur));

	inRect = inRect.enlarge(brad);

	TDimension inRectSize(tceil(inRect.getLx()), tceil(inRect.getLy()));

	TTile inTile;
	m_input->allocateAndCompute(inTile, inRect.getP00(), inRectSize, tileRas, frame, riNew);

	TPointD inTilePosRi = inTile.m_pos;

	//Update quads by the scale factors
	p00_b = riNew.m_affine * p00_b;
	p10_b = riNew.m_affine * p10_b;
	p01_b = riNew.m_affine * p01_b;
	p11_b = riNew.m_affine * p11_b;

	p00_a = ri.m_affine * p00_a;
	p10_a = ri.m_affine * p10_a;
	p01_a = ri.m_affine * p01_a;
	p11_a = ri.m_affine * p11_a;

	PerspectiveDistorter perpDistorter(
		p00_b - inTile.m_pos, p10_b - inTile.m_pos, p01_b - inTile.m_pos, p11_b - inTile.m_pos,
		p00_a, p10_a, p01_a, p11_a);

	BilinearDistorter bilDistorter(
		p00_b - inTile.m_pos, p10_b - inTile.m_pos, p01_b - inTile.m_pos, p11_b - inTile.m_pos,
		p00_a, p10_a, p01_a, p11_a);

	TQuadDistorter *distorter;
	if (m_distortType->getValue() == PERSPECTIVE)
		distorter = &perpDistorter;
	else if (m_distortType->getValue() == BILINEAR)
		distorter = &bilDistorter;
	else
		assert(0);

	if (m_isCastShadow) {
		TRaster32P ras32 = inTile.getRaster();
		TRaster64P ras64 = inTile.getRaster();

		if (ras32) {
			if (m_fade->getValue(frame) > 0)
				doFade(ras32, m_color->getValue(frame), m_fade->getValue(frame) / 100.0);
			if (brad > 0)
				doBlur(ras32, upBlur, downBlur,
					   m_upTransp->getValue(frame) / 100.0, m_downTransp->getValue(frame) / 100.0,
					   inBBox.y0 - inTile.m_pos.y, inBBox.y1 - inTile.m_pos.y);
			else if (m_upTransp->getValue(frame) > 0 || m_downTransp->getValue(frame) > 0)
				doTransparency(ras32, m_upTransp->getValue(frame) / 100.0, m_downTransp->getValue(frame) / 100.0,
							   inBBox.y0 - inTile.m_pos.y, inBBox.y1 - inTile.m_pos.y);
		} else if (ras64) {
			if (m_fade->getValue(frame) > 0)
				doFade(ras64, toPixel64(m_color->getValue(frame)), m_fade->getValue(frame) / 100.0);
			if (brad > 0)
				doBlur(ras64, upBlur, downBlur,
					   m_upTransp->getValue(frame) / 100.0, m_downTransp->getValue(frame) / 100.0,
					   inBBox.y0 - inTile.m_pos.y, inBBox.y1 - inTile.m_pos.y);
			else if (m_upTransp->getValue(frame) > 0 || m_downTransp->getValue(frame) > 0)
				doTransparency(ras64, m_upTransp->getValue(frame) / 100.0, m_downTransp->getValue(frame) / 100.0,
							   inBBox.y0 - inTile.m_pos.y, inBBox.y1 - inTile.m_pos.y);
		} else
			assert(false);
	}

	distort(tileRas, inTile.getRaster(), *distorter, convert(tile.m_pos), TRop::Bilinear);
}