Пример #1
0
MarimontOTF::MarimontOTF( const ViewingConditions &viewCond,
  int cols, int rows, float adaptationLuminance )
{
  const float n_p = 1.336;
  const float f_p = 22.2888e-3;
  const float D0 = n_p/f_p;

  const float c = 3.434e3;

  const float q1 = 1.7312;
  const float q2 = 0.63346;
  const float q3 = 0.21410;

  filter = new pfs::Array2DImpl( cols/2+1, rows/2+1 );

  
  int filterWidth=filter->getCols();
  int filterHeight=filter->getRows();
  
  float meanObserverDistance = (viewCond.minDistance + viewCond.maxDistance)/2;
  float pix_per_deg = viewCond.getPixelsPerDegree( meanObserverDistance );

  float x_norm = 0.5 / filterWidth, y_norm = 0.5 / filterHeight;

  float dx, dy;
  int x, y;

  float p = getPupilDiameter( adaptationLuminance );

  std::cerr << "Creating OTF filter..";

  std::cerr << "(pupil diameter " << p*1e3 << "mm for adaptation lum " << adaptationLuminance << "cd/m^2)";  

  for (y = 0, dy = 0.0; y < filterHeight; y ++, dy += y_norm)
  {
    for (x = 0, dx = 0.0; x < filterWidth; x ++, dx += x_norm)
    {
      float v = pix_per_deg * sqrtf((float)(dx * dx + dy * dy));
      if( v == 0 ) v = 0.1;

      const int lefSize = sizeof( luminanceEfficiencyFunction ) / sizeof( SpectralSensitivity );
      float H = 0;
      for( int l = 0; l < lefSize; l++ ) {
        
        const float lambda = luminanceEfficiencyFunction[l].lambda*1e-9;
    
        const float s = c*(lambda / (D0*p)) * v;
        
        const float D_lambda = q1 - (q2/(lambda*1e6-q3));
        const float w20 = p*p/2 * D0 * D_lambda / (D0 + D_lambda);
        const float alpha = 4*M_PI/lambda * w20 * fabsf( s );
        const float py_max = sqrtf( (1-(s/2))*(1-(s/2)) );

        const float dpy = py_max/10;
        float h = 0;
        for( float py = 0; py <= py_max; py += dpy ) {  
          h += 4/(M_PI*alpha)*sinf( alpha*(sqrtf(1 - py*py) - fabsf(s)/2) )*dpy;
        }
        H += h*luminanceEfficiencyFunction[l].weight;
      }      

      (*filter)(x,y) = H * (0.3481+0.6519*exp(-0.1212*v));
      
    }
  }

  (*filter)(0,0) = max( (*filter)(1,0), (*filter)(0,1) );

  normalizeToMax( filter );

  dumpImageAspect->dump( "filter_otf.pfs", filter, "Y" );
  
  std::cerr << ".\n";  
   
}