TePDIContrast.cpp

Go to the documentation of this file.
00001 #include "TePDIContrast.hpp"
00002 
00003 #include "../kernel/TeAgnostic.h"
00004 #include "TePDITypes.hpp"
00005 #include "TePDIUtils.hpp"
00006 #include "TePDIHistogram.hpp"
00007 #include "TePDIMatrix.hpp"
00008 
00009 #include <math.h>
00010 #include <float.h>
00011 
00012 
00013 TePDIContrast::TePDIContrast()
00014 {
00015 }
00016 
00017 
00018 TePDIContrast::~TePDIContrast()
00019 {
00020 }
00021 
00022 
00023 bool TePDIContrast::RunImplementation()
00024 {
00025   /* Getting general parameters */
00026 
00027   TePDIContrastType contrast_type;
00028   params_.GetParameter( "contrast_type", contrast_type );
00029 
00030   TePDITypes::TePDIRasterPtrType inRaster;
00031   int input_band = 0;
00032   if( params_.CheckParameter< TePDITypes::TePDIRasterPtrType >( 
00033     "input_image" ) ) {
00034     
00035     params_.GetParameter( "input_image", inRaster );
00036     params_.GetParameter( "input_band", input_band );
00037   }
00038 
00039   int output_band = 0;
00040   TePDITypes::TePDIRasterPtrType outRaster;
00041   if( params_.CheckParameter< TePDITypes::TePDIRasterPtrType >( 
00042     "output_image" ) ) {
00043     
00044     params_.GetParameter( "output_image", outRaster );
00045     params_.GetParameter( "output_band", output_band );  
00046   }  
00047   
00048   double min_level = 0;
00049   double max_level = 0;
00050   if( params_.CheckParameter< double >( "min_level" ) ) {
00051     
00052     params_.GetParameter( "min_level", min_level );
00053   }
00054   if( params_.CheckParameter< double >( "max_level" ) ) {
00055     
00056     params_.GetParameter( "max_level", max_level );
00057   }
00058   
00059   TePDIRgbPalette::pointer palette;
00060   if( params_.CheckParameter< TePDIRgbPalette::pointer >( "rgb_palette" ) ) {
00061   
00062     params_.GetParameter( "rgb_palette", palette );
00063   }
00064   
00065   /* output dumyy value definition */
00066  
00067   bool output_raster_uses_dummy = false;
00068   double output_raster_dummy = 0;
00069   
00070   if( outRaster.isActive() ) {
00071     output_raster_uses_dummy = outRaster->params().useDummy_;
00072     
00073     if( output_raster_uses_dummy ) {
00074       output_raster_dummy = outRaster->params().dummy_[ 0 ];
00075     }    
00076   }
00077   
00078   if( params_.CheckParameter< double >( "dummy_value" ) ) {
00079     
00080     params_.GetParameter( "dummy_value", output_raster_dummy );
00081     
00082     output_raster_uses_dummy = true;
00083   }  
00084   
00085   /* Reseting output raster */
00086   
00087   if( outRaster.isActive() ) {
00088     switch( contrast_type ) {
00089       case TePDIContrastSimpleSlicer :
00090       {
00091         bool output_reset_not_needed = true;
00092         
00093         if( ! params_.CheckParameter< int >( "restrict_out_reset" ) ) {
00094           output_reset_not_needed = false;
00095         }
00096         
00097         if( output_reset_not_needed &&
00098           ( inRaster->params().nlines_ != outRaster->params().nlines_ ) ) {
00099            
00100           output_reset_not_needed = false; 
00101         }
00102         
00103         if( output_reset_not_needed &&
00104           ( inRaster->params().ncols_ != outRaster->params().ncols_ ) ) {
00105            
00106           output_reset_not_needed = false; 
00107         }
00108         
00109         if( output_reset_not_needed &&
00110           ( output_band >= outRaster->params().nBands() ) ) {
00111            
00112           output_reset_not_needed = false; 
00113         }
00114         
00115         if( output_reset_not_needed )
00116         { 
00117           if( inRaster->projection() )
00118           {
00119             if( outRaster->projection() )
00120             {
00121               if( !( (*inRaster->projection()) == (*outRaster->projection()) ) )
00122               {
00123                 output_reset_not_needed = false;
00124               }
00125             }
00126             else
00127             {
00128               output_reset_not_needed = false;
00129             }
00130           }
00131           else
00132           {
00133             if( outRaster->projection() )
00134             {
00135               output_reset_not_needed = false;
00136             }
00137           }
00138         }
00139         
00140         if( output_reset_not_needed &&
00141           ( inRaster->params().box() != outRaster->params().box() ) ) 
00142         {
00143            
00144           output_reset_not_needed = false; 
00145         }
00146         
00147         if( output_reset_not_needed &&
00148           ( inRaster->params().photometric_[ 0 ] != TeRasterParams::TePallete 
00149           ) ) 
00150         {
00151            
00152           output_reset_not_needed = false; 
00153         }        
00154         
00155         if( output_reset_not_needed &&
00156             ( ( outRaster->params().useDummy_ == output_raster_uses_dummy ) ?
00157               false :
00158               ( outRaster->params().useDummy_ ? 
00159                 ( outRaster->params().dummy_[ 0 ] != output_raster_dummy ) :
00160                 false
00161               ) 
00162             )
00163           ) {
00164            
00165           output_reset_not_needed = false; 
00166         }   
00167               
00168         if( ! output_reset_not_needed ) 
00169         {
00170           TeRasterParams new_outRaster_params = outRaster->params();
00171           new_outRaster_params.nBands( output_band + 1 );
00172           if( inRaster->projection() == 0 ) {
00173             new_outRaster_params.projection( 0 );
00174           } else {
00175             new_outRaster_params.projection( inRaster->projection() );
00176           }
00177           new_outRaster_params.boxResolution( inRaster->params().box().x1(), 
00178             inRaster->params().box().y1(), inRaster->params().box().x2(), 
00179             inRaster->params().box().y2(), 
00180             inRaster->params().resx_, inRaster->params().resy_ );
00181             
00182           new_outRaster_params.setPhotometric( TeRasterParams::TePallete, -1 );
00183           
00184           new_outRaster_params.lutr_.clear();
00185           new_outRaster_params.lutg_.clear();
00186           new_outRaster_params.lutb_.clear();
00187                   new_outRaster_params.lutClassName_.clear();
00188 
00189           TePDIRgbPalette::iterator pal_it = palette->begin();
00190           TePDIRgbPalette::iterator pal_it_end = palette->end();
00191           for( unsigned int lut_index = 0 ; lut_index < palette->size() ;
00192               ++lut_index ) {
00193     
00194             new_outRaster_params.lutr_.push_back( 
00195               (unsigned short)pal_it->second.red_ );
00196             new_outRaster_params.lutg_.push_back( 
00197               (unsigned short)pal_it->second.green_ );
00198             new_outRaster_params.lutb_.push_back( 
00199               (unsigned short)pal_it->second.blue_ );
00200 
00201             ++pal_it;
00202           }
00203 
00204                   new_outRaster_params.lutClassName_.resize(palette->size());
00205           
00206           if( output_raster_uses_dummy ) {
00207             new_outRaster_params.setDummy( output_raster_dummy, -1 );
00208           } else {
00209             new_outRaster_params.useDummy_ = false;
00210           }
00211             
00212           TEAGN_TRUE_OR_RETURN( outRaster->init( new_outRaster_params ),            
00213             "Output raster reset error" );           
00214         }
00215       
00216         break;
00217       }  
00218       default :
00219       {
00220         /* Reseting output raster */
00221         
00222         bool output_reset_not_needed = true;
00223         
00224         if( ! params_.CheckParameter< int >( "restrict_out_reset" ) ) {
00225           output_reset_not_needed = false;
00226         }
00227         
00228         if( output_reset_not_needed &&
00229           ( inRaster->params().nlines_ != outRaster->params().nlines_ ) ) {
00230            
00231           output_reset_not_needed = false; 
00232         }
00233         
00234         if( output_reset_not_needed &&
00235           ( inRaster->params().ncols_ != outRaster->params().ncols_ ) ) {
00236            
00237           output_reset_not_needed = false; 
00238         }
00239         
00240         if( output_reset_not_needed &&
00241           ( output_band >= outRaster->params().nBands() ) ) {
00242            
00243           output_reset_not_needed = false; 
00244         }
00245         
00246         if( output_reset_not_needed &&
00247           ( 
00248             ( inRaster->projection() == outRaster->projection() ) ? 
00249             false : 
00250             ( 
00251               ( inRaster->projection() == 0 ) ?
00252               true :
00253               (
00254                 ( outRaster->projection() == 0 ) ? 
00255                 true :
00256                 ( inRaster->projection()->name() == 
00257                   outRaster->projection()->name() ) ? false : true
00258               )
00259             ) 
00260           )        
00261          ) {
00262            
00263           output_reset_not_needed = false; 
00264         }
00265         
00266         if( output_reset_not_needed &&
00267           ( inRaster->params().box() != outRaster->params().box() ) ) {
00268            
00269           output_reset_not_needed = false; 
00270         }
00271         
00272         if( output_reset_not_needed &&
00273             ( ( outRaster->params().useDummy_ == output_raster_uses_dummy ) ?
00274               false :
00275               ( outRaster->params().useDummy_ ? 
00276                 ( outRaster->params().dummy_[ 0 ] != output_raster_dummy ) :
00277                 false
00278               ) 
00279             )
00280           ) {
00281            
00282           output_reset_not_needed = false; 
00283         }          
00284         
00285         if( ! output_reset_not_needed ) {
00286         
00287           TeRasterParams new_outRaster_params = outRaster->params();
00288           new_outRaster_params.nBands( output_band + 1 );
00289           if( inRaster->projection() == 0 ) {
00290             new_outRaster_params.projection( 0 );
00291           } else {
00292             TeSharedPtr< TeProjection > proj( TeProjectionFactory::make( 
00293               inRaster->projection()->params() ) );          
00294             new_outRaster_params.projection( proj.nakedPointer() );
00295           }
00296           new_outRaster_params.boxResolution( inRaster->params().box().x1(), 
00297             inRaster->params().box().y1(), inRaster->params().box().x2(), 
00298             inRaster->params().box().y2(), 
00299             inRaster->params().resx_, inRaster->params().resy_ );            
00300             
00301           if( output_raster_uses_dummy ) {
00302             new_outRaster_params.setDummy( output_raster_dummy, -1 );
00303           } else {
00304             new_outRaster_params.useDummy_ = false;
00305           }            
00306           
00307           new_outRaster_params.setPhotometric( TeRasterParams::TeMultiBand );
00308             
00309           TEAGN_TRUE_OR_RETURN( outRaster->init( new_outRaster_params ),
00310             "Output raster reset error" );             
00311         }
00312         
00313         break;
00314       }
00315     }
00316   }
00317   
00318   /* Getting output channel range */
00319   
00320   double output_channel_min_level = 0;
00321   double output_channel_max_level = 0;
00322   
00323   if( params_.CheckParameter< double >( "output_channel_min_level" ) ) {
00324     params_.GetParameter( "output_channel_min_level",
00325       output_channel_min_level );
00326     params_.GetParameter( "output_channel_max_level",
00327       output_channel_max_level );
00328   } else {
00329     TEAGN_TRUE_OR_RETURN( TePDIUtils::TeGetRasterMinMaxBounds(
00330       outRaster, output_band, output_channel_min_level,
00331       output_channel_max_level ), "Unable to get raster channel level bounds" );  
00332   }
00333       
00334   /* Building a lut suitable for each algorithm */
00335     
00336   TePDITypes::TePDILutType lut;
00337   bool hist_based_lut = false;
00338   bool fixed_step_lut = false;
00339   
00340   switch( contrast_type ) {
00341     case TePDIContrastMinMax :
00342     {
00343       TePDITypes::TePDILutType baselut;
00344       TEAGN_TRUE_OR_RETURN( getBaseLut( baselut, hist_based_lut,
00345         output_raster_uses_dummy, output_raster_dummy ),
00346         "Error getting base lut" );
00347       
00348       lut = GetMinMaxLut( output_channel_min_level, output_channel_max_level,
00349         baselut );
00350   
00351       break;
00352     }
00353     case TePDIContrastLinear :
00354     {
00355       TePDITypes::TePDILutType baselut;
00356       TEAGN_TRUE_OR_RETURN( getBaseLut( baselut, hist_based_lut,
00357         output_raster_uses_dummy, output_raster_dummy ),
00358         "Error getting base lut" );
00359             
00360       lut = GetLinearLut( baselut,
00361         min_level, max_level, output_channel_min_level, output_channel_max_level );
00362   
00363       break;
00364     }
00365     case TePDIContrastSquareRoot :
00366     {
00367       TePDITypes::TePDILutType baselut;
00368       TEAGN_TRUE_OR_RETURN( getBaseLut( baselut, hist_based_lut,
00369         output_raster_uses_dummy, output_raster_dummy ),
00370         "Error getting base lut" );    
00371     
00372       lut = GetSquareRootLut( baselut,
00373         min_level, max_level, output_channel_min_level, output_channel_max_level );
00374   
00375       break;
00376     }
00377     case TePDIContrastSquare :
00378     {
00379       TePDITypes::TePDILutType baselut;
00380       TEAGN_TRUE_OR_RETURN( getBaseLut( baselut, hist_based_lut,
00381         output_raster_uses_dummy, output_raster_dummy ),
00382         "Error getting base lut" ); 
00383             
00384       lut = GetSquareLut( baselut,
00385         min_level, max_level, output_channel_min_level, output_channel_max_level );
00386   
00387       break;
00388     }
00389     case TePDIContrastLog :
00390     {
00391       TePDITypes::TePDILutType baselut;
00392       TEAGN_TRUE_OR_RETURN( getBaseLut( baselut, hist_based_lut,
00393         output_raster_uses_dummy, output_raster_dummy ),
00394         "Error getting base lut" ); 
00395             
00396       lut = GetLogLut( baselut,
00397         min_level, max_level, output_channel_min_level, output_channel_max_level );
00398   
00399       break;
00400     }
00401     case TePDIContrastNegative :
00402     {
00403       TePDITypes::TePDILutType baselut;
00404       TEAGN_TRUE_OR_RETURN( getBaseLut( baselut, hist_based_lut,
00405         output_raster_uses_dummy, output_raster_dummy ),
00406         "Error getting base lut" ); 
00407             
00408       lut = GetNegativeLut( baselut,
00409         min_level, max_level, output_channel_min_level, output_channel_max_level );
00410  
00411       break;
00412     }
00413     case TePDIContrastHistEqualizer :
00414     {
00415       TePDIHistogram::pointer histogram;
00416       TEAGN_TRUE_OR_RETURN( getHistogram( histogram, output_raster_uses_dummy, 
00417         output_raster_dummy ), "Unable to get histogram" );
00418         
00419       fixed_step_lut = histogram->hasFixedStep();
00420       hist_based_lut = true;
00421     
00422       lut = GetHistEqualizerLut( histogram,
00423         output_channel_min_level, output_channel_max_level );
00424   
00425       break;
00426     }
00427     case TePDIContrastSimpleSlicer :
00428     {
00429       TePDIHistogram::pointer histogram;
00430       TEAGN_TRUE_OR_RETURN( getHistogram( histogram, output_raster_uses_dummy, 
00431         output_raster_dummy ), "Unable to get histogram" );
00432         
00433       fixed_step_lut = histogram->hasFixedStep();
00434       hist_based_lut = true;
00435             
00436       GetSimpleSlicerLut( histogram,
00437         palette,  min_level, max_level, lut );
00438   
00439       break;
00440     }
00441     case TePDIContrastStat :
00442     {
00443       TePDIHistogram::pointer histogram;
00444       TEAGN_TRUE_OR_RETURN( getHistogram( histogram, output_raster_uses_dummy, 
00445         output_raster_dummy ), "Unable to get histogram" );
00446         
00447       fixed_step_lut = histogram->hasFixedStep();
00448       hist_based_lut = true;
00449     
00450       double target_mean = 0;
00451       params_.GetParameter( "target_mean", target_mean );
00452       
00453       double target_variance = 0;
00454       params_.GetParameter( "target_variance", target_variance );
00455       GetStatLut( histogram, target_mean, target_variance,
00456         output_channel_min_level, output_channel_max_level, lut );
00457   
00458       break;
00459     }    
00460     default :
00461     {
00462       TEAGN_LOG_AND_THROW( "Unsuported contrast type" );
00463       break;
00464     }
00465   }
00466   
00467   /* Updating the output lut, if present */
00468   
00469   if( params_.CheckParameter< TePDITypes::TePDILutPtrType >( 
00470     "outlut" ) ) {
00471 
00472     TePDITypes::TePDILutPtrType outlut;  
00473     params_.GetParameter( "outlut", outlut );
00474     
00475     *outlut = lut;
00476   }    
00477 
00478   /* Rendering output raster */
00479   
00480   if( outRaster.isActive() ) {
00481     if( hist_based_lut ) {
00482       TEAGN_TRUE_OR_RETURN( RemapLevels( inRaster, lut, input_band, 
00483         output_band, outRaster, output_raster_uses_dummy, output_raster_dummy, 
00484         fixed_step_lut ), "Level remapping error" );
00485     } else {
00486       TEAGN_TRUE_OR_RETURN( FullRangeLutRemapLevels( inRaster, lut, 
00487         input_band, output_band, outRaster, output_raster_uses_dummy, 
00488         output_raster_dummy ), "Level remapping error" );    
00489     }
00490   }
00491   
00492   /* Returning the generated histogram, if required */
00493   
00494   if( params_.CheckParameter< TePDIHistogram::pointer >( 
00495     "output_original_histogram" ) ) {
00496     
00497     TePDIHistogram::pointer curr_histo_ptr;
00498     TEAGN_TRUE_OR_RETURN( getHistogram( curr_histo_ptr,
00499       output_raster_uses_dummy, output_raster_dummy ), 
00500         "Unable to get histogram" );      
00501   
00502     TePDIHistogram::pointer output_original_histogram;
00503     params_.GetParameter( "output_original_histogram", 
00504       output_original_histogram );
00505     
00506     (*output_original_histogram) = (*curr_histo_ptr);
00507   }
00508   
00509   /* Returning output_enhanced_histogram, if required */
00510   
00511   if( params_.CheckParameter< TePDIHistogram::pointer >( 
00512     "output_enhanced_histogram" ) ) {
00513     
00514     TePDIHistogram::pointer curr_histo_ptr;
00515     TEAGN_TRUE_OR_RETURN( getHistogram( curr_histo_ptr,
00516       output_raster_uses_dummy, output_raster_dummy ), 
00517         "Unable to get histogram" );      
00518   
00519     TePDIHistogram::pointer output_enhanced_histogram;
00520     params_.GetParameter( "output_enhanced_histogram", 
00521       output_enhanced_histogram );
00522     
00523     TePDIHistogram::iterator curr_histo_it = curr_histo_ptr->begin();
00524     TePDIHistogram::iterator curr_histo_it_end = curr_histo_ptr->end();
00525     TePDITypes::TePDILutType::iterator lut_it_end = lut.end();
00526     TePDITypes::TePDILutType::iterator found_lut_mapping_it;
00527     
00528     while( curr_histo_it != curr_histo_it_end ) {
00529       found_lut_mapping_it = lut.find( curr_histo_it->first );
00530       
00531       if( found_lut_mapping_it != lut_it_end ) {
00532         (*output_enhanced_histogram)[ found_lut_mapping_it->second ]
00533           += curr_histo_it->second;
00534       }
00535     
00536       ++curr_histo_it;
00537     }
00538   }  
00539   
00540   return true;
00541 }
00542 
00543 
00544 bool TePDIContrast::CheckParameters( 
00545   const TePDIParameters& parameters ) const
00546 {
00547   /* Checking input raster */
00548 
00549   if( parameters.CheckParameter< TePDITypes::TePDIRasterPtrType >( 
00550     "input_image" ) ) {
00551     
00552     TePDITypes::TePDIRasterPtrType inRaster;
00553     
00554     if( ! parameters.GetParameter( "input_image", inRaster ) ) {
00555   
00556       TEAGN_LOGERR( "Missing parameter: input_image" );
00557       return false;
00558     }
00559     if( ! inRaster.isActive() ) {
00560   
00561       TEAGN_LOGERR( "Invalid parameter: input_image inactive" );
00562       return false;
00563     }
00564     if( inRaster->params().status_ == TeRasterParams::TeNotReady ) {
00565   
00566     TEAGN_LOGERR( "Invalid parameter: input_image not ready" );
00567       return false;
00568     }
00569     
00570     /* Checking input band */
00571     
00572     int input_band;
00573     TEAGN_TRUE_OR_RETURN( parameters.GetParameter( "input_band", input_band ),
00574       "Missing parameter: input_band" );
00575     TEAGN_TRUE_OR_RETURN( ( ( input_band >= 0 ) && 
00576       ( input_band < inRaster->nBands() ) ),
00577       "Invalid parameter: input_band" );     
00578       
00579     /* Checking photometric interpretation */
00580     
00581     TEAGN_TRUE_OR_RETURN( ( 
00582       ( inRaster->params().photometric_[ input_band ] == 
00583         TeRasterParams::TeRGB ) ||
00584       ( inRaster->params().photometric_[ input_band ] == 
00585         TeRasterParams::TeMultiBand ) ),
00586     "Invalid parameter - input_image (invalid photometric interpretation)" );    
00587   }
00588         
00589   /* checking output raster, if present */
00590   
00591   TePDITypes::TePDIRasterPtrType output_image;
00592   if( parameters.CheckParameter< TePDITypes::TePDIRasterPtrType >( 
00593     "output_image" ) ) {
00594     
00595     TEAGN_TRUE_OR_RETURN( parameters.GetParameter( "output_image", 
00596       output_image ),  "Missing parameter: output_image" );
00597     TEAGN_TRUE_OR_RETURN( output_image.isActive(),
00598       "Invalid parameter: output_image inactive" );
00599     TEAGN_TRUE_OR_RETURN( output_image->params().status_ != 
00600       TeRasterParams::TeNotReady, 
00601       "Invalid parameter: output_image not ready" );
00602       
00603     /* Checking output_band */
00604     
00605     int output_band;
00606     TEAGN_TRUE_OR_RETURN( parameters.GetParameter( "output_band", 
00607       output_band ), "Missing parameter: output_band" );
00608     TEAGN_TRUE_OR_RETURN( ( output_band >= 0 ),
00609       "Invalid parameter: output_band" ); 
00610       
00611     /* Input raster needed if output_image is present */
00612     
00613     TEAGN_TRUE_OR_RETURN( 
00614       parameters.CheckParameter< TePDITypes::TePDIRasterPtrType >( 
00615       "input_image" ), "Missing parameter: input_image" );
00616   }
00617 
00618   /* Checking for the correct allowed contrast types */
00619 
00620   TePDIContrastType contrast_type;
00621   if( ! parameters.GetParameter( "contrast_type", contrast_type ) ) {
00622     TEAGN_LOGERR( "Missing parameter: contrast_type" );
00623     return false;
00624   }
00625   TEAGN_CHECK_NOTEQUAL( contrast_type, 0, "Invalid Contrast type" );
00626   if( ( contrast_type != TePDIContrastMinMax ) &&
00627       ( contrast_type != TePDIContrastLinear ) &&
00628       ( contrast_type != TePDIContrastSquareRoot ) &&
00629       ( contrast_type != TePDIContrastSquare ) &&
00630       ( contrast_type != TePDIContrastLog ) &&
00631       ( contrast_type != TePDIContrastNegative ) &&
00632       ( contrast_type != TePDIContrastHistEqualizer ) &&
00633       ( contrast_type != TePDIContrastSimpleSlicer ) &&
00634       ( contrast_type != TePDIContrastStat ) ) {
00635 
00636     TEAGN_LOGERR( "Invalid parameter: contrast_type" );
00637     return false;
00638   }
00639 
00640   /* Checking for min and max required parameters */
00641 
00642   if( ( contrast_type == TePDIContrastLinear ) ||
00643       ( contrast_type == TePDIContrastSquareRoot ) ||
00644       ( contrast_type == TePDIContrastSquare ) ||
00645       ( contrast_type == TePDIContrastLog ) ||
00646       ( contrast_type == TePDIContrastNegative ) ||
00647       ( contrast_type == TePDIContrastSimpleSlicer ) ) {
00648 
00649     if( ! parameters.CheckParameter< double >( "min_level" ) ) {
00650 
00651       TEAGN_LOGERR( "Missing parameter: min_level" );
00652       return false;
00653     }
00654     if( ! parameters.CheckParameter< double >( "max_level" ) ) {
00655 
00656       TEAGN_LOGERR( "Missing parameter: max_level" );
00657       return false;
00658     }
00659   }
00660 
00661   /* Checking for RGB Palette required parameters */
00662 
00663   if( ( contrast_type == TePDIContrastSimpleSlicer ) ) {
00664     TePDIRgbPalette::pointer rgb_palette;
00665 
00666     if( ( ! parameters.GetParameter( "rgb_palette", rgb_palette ) ) ||
00667         ( ! rgb_palette.isActive() ) ) {
00668 
00669       TEAGN_LOGERR( "Missing parameter: rgb_palette" );
00670       return false;
00671     }
00672   }
00673   
00674   /* checking outlut parameter */
00675   
00676   if( parameters.CheckParameter< TePDITypes::TePDILutPtrType >( 
00677     "outlut" ) ) {
00678 
00679     TePDITypes::TePDILutPtrType outlut;  
00680     parameters.GetParameter( "outlut", outlut );
00681     
00682     TEAGN_TRUE_OR_RETURN( outlut.isActive(),
00683       "Invalid parameter: outlut" );
00684   }
00685   
00686   /* checking input_histogram */
00687   
00688   TePDIHistogram::pointer input_histogram;
00689   
00690   if( parameters.CheckParameter< TePDIHistogram::pointer >( 
00691     "input_histogram" ) ) {
00692   
00693     parameters.GetParameter( "input_histogram", input_histogram );
00694     TEAGN_TRUE_OR_RETURN( input_histogram.isActive(),
00695       "Invalid parameter: input_histogram" );
00696     TEAGN_TRUE_OR_RETURN( ( input_histogram->size() > 0 ),
00697       "Invalid parameter: input_histogram" );
00698   } else {
00699     /* Input raster needed if input_histogram isn't present */
00700     
00701     TEAGN_TRUE_OR_RETURN( 
00702       parameters.CheckParameter< TePDITypes::TePDIRasterPtrType >( 
00703       "input_image" ), "Missing parameter: input_image" );
00704   }
00705   
00706   /* checking output_original_histogram */
00707   
00708   TePDIHistogram::pointer output_original_histogram;
00709   
00710   if( parameters.CheckParameter< TePDIHistogram::pointer >( 
00711     "output_original_histogram" ) ) {
00712   
00713     parameters.GetParameter( "output_original_histogram", 
00714       output_original_histogram );
00715     TEAGN_TRUE_OR_RETURN( output_original_histogram.isActive(),
00716       "Invalid parameter: output_original_histogram" );
00717   }
00718 
00719   /* checking output_enhanced_histogram */
00720   
00721   TePDIHistogram::pointer output_enhanced_histogram;
00722   
00723   if( parameters.CheckParameter< TePDIHistogram::pointer >( 
00724     "output_enhanced_histogram" ) ) {
00725   
00726     parameters.GetParameter( "output_enhanced_histogram", 
00727       output_enhanced_histogram );
00728     TEAGN_TRUE_OR_RETURN( output_enhanced_histogram.isActive(),
00729       "Invalid parameter: output_enhanced_histogram" );
00730   }  
00731   
00732   /* Checking target_mean and target_variance */
00733   
00734   if( ( contrast_type == TePDIContrastStat ) ) {
00735     double target_mean = 0;
00736     TEAGN_TRUE_OR_RETURN( 
00737       parameters.GetParameter( "target_mean", target_mean ),
00738       "Missing parameter: target_mean" );
00739       
00740     double target_variance = 0;
00741     TEAGN_TRUE_OR_RETURN( 
00742       parameters.GetParameter( "target_variance", target_variance ),
00743       "Missing parameter: target_variance" );      
00744   }
00745   
00746   /* Checking input_variance */
00747   
00748   /* if input_variance is zero the algoritm will fail in GetStatLut */
00749   
00750   double input_variance = 0;
00751   
00752   if( parameters.CheckParameter< double >( "input_variance" ) ) {
00753     parameters.GetParameter( "input_variance", input_variance );
00754     
00755     TEAGN_TRUE_OR_RETURN( ( input_variance != 0 ),
00756       "Invalid parameter - input_variance" )
00757   }
00758   
00759   /* Checking output_channel_min_level and output_channel_max_level */
00760   
00761   if( ! output_image.isActive() ) {
00762   
00763     TEAGN_TRUE_OR_RETURN( 
00764       parameters.CheckParameter< double >( "output_channel_min_level" ),
00765       "Missing parameter: output_channel_min_level" );
00766     TEAGN_TRUE_OR_RETURN( 
00767       parameters.CheckParameter< double >( "output_channel_max_level" ),
00768       "Missing parameter: output_channel_max_level" );
00769   }
00770   
00771   return true;
00772 }
00773 
00774 
00775 void TePDIContrast::ResetState( const TePDIParameters& params )
00776 {
00777   if( params != params_ ) {
00778     histo_ptr_.reset();
00779   }
00780 }
00781 
00782 
00783 TePDITypes::TePDILutType TePDIContrast::GetMinMaxLut(
00784   double output_channel_min_level, double output_channel_max_level,
00785   TePDITypes::TePDILutType& base_lut )
00786 {
00787   TEAGN_TRUE_OR_THROW( base_lut.size() != 0, "Invalid base_lut" );
00788   
00789   double lut_max = (-1.0) * DBL_MAX;
00790   double lut_min = DBL_MAX;
00791   
00792   TePDITypes::TePDILutType::iterator it = base_lut.begin();
00793   TePDITypes::TePDILutType::iterator it_end = base_lut.end();
00794   
00795   while( it != it_end ) {
00796     if( it->first < lut_min ) {
00797       lut_min = it->first;
00798     }
00799     if( it->first > lut_max ) {
00800       lut_max = it->first;
00801     }
00802   
00803     ++it;
00804   }
00805 
00806   return GetLinearLut( base_lut, lut_min,
00807     lut_max, output_channel_min_level, output_channel_max_level );
00808 }
00809 
00810 
00811 TePDITypes::TePDILutType TePDIContrast::GetLinearLut(
00812   TePDITypes::TePDILutType& base_lut,
00813   double min, double max,
00814   double output_channel_min_level, double output_channel_max_level )
00815 {
00816   TEAGN_CHECK_NOTEQUAL( base_lut.size(), 0, "Invalid base_lut size" );
00817   TEAGN_TRUE_OR_THROW( max > min, "Invalid max and min values" );
00818 
00819   /* Calculating parameters */
00820 
00821   unsigned int levels = base_lut.size();
00822 
00823   double a = 0;
00824   double b = 0;
00825 
00826   if( max == min ) {
00827     a = (double)levels;
00828     b = -1. * ((double)levels) * min;
00829   } else {
00830     a = ((double)levels) / ( max - min );
00831     b = ( -1. * ((double)levels) * min ) / ( max - min );
00832   }
00833 
00834   /* Generating LUT map using the existing histogram levels */
00835 
00836   TePDITypes::TePDILutType out_lut;
00837 
00838   TePDITypes::TePDILutType::iterator base_lut_it = base_lut.begin();
00839   TePDITypes::TePDILutType::iterator base_lut_it_end = base_lut.end();
00840   
00841   unsigned int progress = 0;
00842   double mapped_level = 0;
00843   StartProgInt( "Building Linear Lut...", base_lut.size() );
00844 
00845   while( base_lut_it != base_lut_it_end ) {
00846     UpdateProgInt( progress );
00847     
00848     if( base_lut_it->first <= min ) {
00849       out_lut[ base_lut_it->first ] = output_channel_min_level;
00850     } else if( base_lut_it->first >= max ) {
00851       out_lut[ base_lut_it->first ] = output_channel_max_level;
00852     } else {
00853       mapped_level = ( a * base_lut_it->first ) + b;
00854       
00855       if( mapped_level < output_channel_min_level ) {
00856         mapped_level = output_channel_min_level;
00857       } else if( mapped_level > output_channel_max_level ) {
00858         mapped_level = output_channel_max_level;
00859       }
00860       
00861       out_lut[ base_lut_it->first ] = mapped_level;
00862     }
00863 
00864     ++progress;
00865     ++base_lut_it;
00866   }
00867 
00868   return out_lut;
00869 }
00870 
00871 
00872 TePDITypes::TePDILutType TePDIContrast::GetSquareRootLut(
00873   TePDITypes::TePDILutType& base_lut,
00874   double min, double max,
00875   double output_channel_min_level, double output_channel_max_level )
00876 {
00877   TEAGN_CHECK_NOTEQUAL( base_lut.size(), 0, "Invalid base_lut size" );
00878   TEAGN_TRUE_OR_THROW( min < max, "Invalid min and max values" );
00879 
00880   unsigned int levels = base_lut.size();
00881 
00882   double factor = ((double)levels) / sqrt( max - min );
00883 
00884   /* Generating LUT map using the existing base lut levels */
00885 
00886   TePDITypes::TePDILutType out_lut;
00887 
00888   TePDITypes::TePDILutType::iterator base_lut_it = base_lut.begin();
00889   TePDITypes::TePDILutType::iterator base_lut_it_end = base_lut.end();
00890   
00891   unsigned int progress = 0;
00892   double mapped_level = 0;
00893   StartProgInt( "Building Square Root Lut...", base_lut.size() );  
00894 
00895   while( base_lut_it != base_lut_it_end ) {
00896     UpdateProgInt( progress );
00897     
00898     if( base_lut_it->first <= min ) {
00899       out_lut[ base_lut_it->first ] = output_channel_min_level;
00900     } else if( base_lut_it->first >= max ) {
00901       out_lut[ base_lut_it->first ] = output_channel_max_level;
00902     } else {
00903       mapped_level = factor * sqrt( base_lut_it->first - min );
00904       
00905       if( mapped_level < output_channel_min_level ) {
00906         mapped_level = output_channel_min_level;
00907       } else if( mapped_level > output_channel_max_level ) {
00908         mapped_level = output_channel_max_level;
00909       }      
00910       
00911       out_lut[ base_lut_it->first ] = mapped_level;
00912     }
00913 
00914     ++progress;
00915     ++base_lut_it;
00916   }
00917 
00918   return out_lut;
00919 }
00920 
00921 
00922 TePDITypes::TePDILutType TePDIContrast::GetSquareLut(
00923   TePDITypes::TePDILutType& base_lut,
00924   double min, double max,
00925   double output_channel_min_level, double output_channel_max_level )
00926 {
00927   TEAGN_CHECK_NOTEQUAL( base_lut.size(), 0, "Invalid base_lut size" );
00928   TEAGN_TRUE_OR_THROW( min < max, "Invalid min and max values" );
00929 
00930   unsigned int levels = base_lut.size();
00931 
00932   double factor = ((double)levels) / pow( (max - min), 2 );
00933 
00934   /* Generating LUT map using the existing base lut levels */
00935 
00936   TePDITypes::TePDILutType out_lut;
00937 
00938   TePDITypes::TePDILutType::iterator base_lut_it = base_lut.begin();
00939   TePDITypes::TePDILutType::iterator base_lut_it_end = base_lut.end();
00940 
00941   unsigned int progress = 0;
00942   double mapped_level = 0;
00943   StartProgInt( "Building Square Lut...", base_lut.size() ); 
00944     
00945   while( base_lut_it != base_lut_it_end ) {
00946     UpdateProgInt( progress );
00947     
00948     if( base_lut_it->first <= min ) {
00949       out_lut[ base_lut_it->first ] = output_channel_min_level;
00950     } else if( base_lut_it->first >= max ) {
00951       out_lut[ base_lut_it->first ] = output_channel_max_level;
00952     } else {
00953       mapped_level = factor * pow( base_lut_it->first - min, 2 );
00954       
00955       if( mapped_level < output_channel_min_level ) {
00956         mapped_level = output_channel_min_level;
00957       } else if( mapped_level > output_channel_max_level ) {
00958         mapped_level = output_channel_max_level;
00959       }        
00960       
00961       out_lut[ base_lut_it->first ] = mapped_level;
00962     }
00963 
00964     ++progress;
00965     ++base_lut_it;
00966   }
00967 
00968   return out_lut;
00969 }
00970 
00971 
00972 TePDITypes::TePDILutType TePDIContrast::GetLogLut(
00973   TePDITypes::TePDILutType& base_lut,
00974   double min, double max,
00975   double output_channel_min_level, double output_channel_max_level )
00976 {
00977   TEAGN_CHECK_NOTEQUAL( base_lut.size(), 0, "Invalid base_lut size" );
00978   TEAGN_TRUE_OR_THROW( max > ( min+1 ), "Invalid min and max values" );
00979 
00980   unsigned int levels = base_lut.size();
00981 
00982   double factor = ((double)levels) / log10( max - min + 1 );
00983 
00984   /* Generating LUT map using the existing base_lut levels */
00985 
00986   TePDITypes::TePDILutType out_lut;
00987 
00988   TePDITypes::TePDILutType::iterator base_lut_it = base_lut.begin();
00989   TePDITypes::TePDILutType::iterator base_lut_it_end = base_lut.end();
00990 
00991   unsigned int progress = 0;
00992   double mapped_level = 0;
00993   StartProgInt( "Building Log Lut...", base_lut.size() ); 
00994     
00995   while( base_lut_it != base_lut_it_end ) {
00996     UpdateProgInt( progress );
00997     
00998     if( base_lut_it->first <= min ) {
00999       out_lut[ base_lut_it->first ] = output_channel_min_level;
01000     } else if( base_lut_it->first >= max ) {
01001       out_lut[ base_lut_it->first ] = output_channel_max_level;
01002     } else {
01003       mapped_level = factor * log10( base_lut_it->first - min + 1 );
01004       
01005       if( mapped_level < output_channel_min_level ) {
01006         mapped_level = output_channel_min_level;
01007       } else if( mapped_level > output_channel_max_level ) {
01008         mapped_level = output_channel_max_level;
01009       }        
01010     
01011       out_lut[ base_lut_it->first ] = mapped_level;
01012     }
01013 
01014     ++progress;
01015     ++base_lut_it;
01016   }
01017 
01018   return out_lut;
01019 }
01020 
01021 
01022 TePDITypes::TePDILutType TePDIContrast::GetNegativeLut(
01023   TePDITypes::TePDILutType& base_lut,
01024   double min, double max,
01025   double output_channel_min_level, double output_channel_max_level )
01026 {
01027   TEAGN_CHECK_NOTEQUAL( base_lut.size(), 0, "Invalid base_lut size" );
01028   TEAGN_TRUE_OR_THROW( max > min, "Invalid max and min values" );
01029 
01030   /* Calculating parameters */
01031 
01032   unsigned int levels = base_lut.size();
01033 
01034   double a = -1. * ((double)levels) / ( max - min );
01035   double b = ( ((double)levels) * max ) / ( max - min );
01036 
01037   /* Generating LUT map using the existing base_lut levels */
01038 
01039   TePDITypes::TePDILutType out_lut;
01040 
01041   TePDITypes::TePDILutType::iterator base_lut_it = base_lut.begin();
01042   TePDITypes::TePDILutType::iterator base_lut_it_end = base_lut.end();
01043 
01044   unsigned int progress = 0;
01045   double mapped_level = 0;
01046   StartProgInt( "Building Negative Lut...", base_lut.size() ); 
01047     
01048   while( base_lut_it != base_lut_it_end ) {
01049     UpdateProgInt( progress );
01050     
01051     if( base_lut_it->first <= min ) {
01052       out_lut[ base_lut_it->first ] = output_channel_max_level;
01053     } else if( base_lut_it->first >= max ) {
01054       out_lut[ base_lut_it->first ] = output_channel_min_level;
01055     } else {
01056       mapped_level = ( a * base_lut_it->first ) + b;
01057       
01058       if( mapped_level < output_channel_min_level ) {
01059         mapped_level = output_channel_min_level;
01060       } else if( mapped_level > output_channel_max_level ) {
01061         mapped_level = output_channel_max_level;
01062       }
01063       
01064       out_lut[ base_lut_it->first ] = mapped_level;
01065     }
01066 
01067     ++progress;
01068     ++base_lut_it;
01069   }
01070 
01071   return out_lut;
01072 }
01073 
01074 TePDITypes::TePDILutType TePDIContrast::GetHistEqualizerLut(
01075   TePDIHistogram::pointer hist,
01076   double output_channel_min_level, double output_channel_max_level )
01077 {
01078   TEAGN_TRUE_OR_THROW( hist->size() > 1, "Invalid histogram size" );
01079   TEAGN_TRUE_OR_THROW( ( output_channel_max_level > output_channel_min_level ),
01080     "Invalid paramters output_channel_max_level <= output_channel_min_level" );
01081   TEAGN_TRUE_OR_THROW( ( hist->GetMaxCount() > 0 ),
01082     "Invalid histogram" );
01083     
01084   /* Generating the accumulative matrix */
01085 
01086   TePDIHistogram::iterator in_hist_it = hist->begin();
01087   TePDIHistogram::iterator in_hist_it_end = hist->end();
01088 
01089   TePDIMatrix< double > accumulative_matrix;
01090   TEAGN_TRUE_OR_THROW( accumulative_matrix.Reset( hist->size(), 2 ),
01091     "Matrix reset error" );
01092     
01093   accumulative_matrix( 0, 0 ) = in_hist_it->first;
01094   accumulative_matrix( 0, 1 ) = (double)in_hist_it->second;
01095   ++in_hist_it;
01096   
01097   unsigned int accumulative_matrix_line = 1;
01098   double hist_population = (double)in_hist_it->second;
01099   
01100   StartProgInt( "Building Histogram Equalizer Lut...", 2 * hist->size() );
01101   
01102   while( in_hist_it != in_hist_it_end ) { 
01103     accumulative_matrix( accumulative_matrix_line, 0 ) = in_hist_it->first;
01104     accumulative_matrix( accumulative_matrix_line, 1 ) =
01105       accumulative_matrix( accumulative_matrix_line - 1, 1 ) +
01106       (double)in_hist_it->second;
01107       
01108      hist_population += (double)in_hist_it->second;
01109   
01110     ++accumulative_matrix_line;
01111     ++in_hist_it;
01112     
01113     IncProgInt();
01114   }
01115   
01116   /* Creating the look-up table */
01117 
01118   double total_levels_nmb = (double)hist->size();
01119   double mapped_level = 0;
01120   TePDITypes::TePDILutType out_lut;
01121   
01122   for( accumulative_matrix_line = 0 ; 
01123     accumulative_matrix_line < accumulative_matrix.GetLines() ;
01124     ++accumulative_matrix_line ) {
01125     
01126     mapped_level = ( accumulative_matrix( accumulative_matrix_line, 1 ) *
01127       total_levels_nmb ) / hist_population;
01128       
01129     if( mapped_level < output_channel_min_level ) {
01130       mapped_level = output_channel_min_level;
01131     } else if( mapped_level > output_channel_max_level ) {
01132       mapped_level = output_channel_max_level;
01133     }
01134     
01135     out_lut[ accumulative_matrix( accumulative_matrix_line, 0 ) ] = 
01136       mapped_level;
01137       
01138     IncProgInt();  
01139   }
01140   
01141   StopProgInt();
01142   
01143   return out_lut;
01144 }
01145 
01146 
01147 void TePDIContrast::GetSimpleSlicerLut(
01148   TePDIHistogram::pointer hist,
01149   TePDIRgbPalette::pointer in_palette,
01150   double min,
01151   double max,
01152   TePDITypes::TePDILutType& out_lut )
01153 {
01154   TEAGN_TRUE_OR_THROW( ( hist->size() > 0 ), "Invalid histogram size" );
01155   TEAGN_TRUE_OR_THROW( max > min, "Invalid max and min values" );
01156   TEAGN_TRUE_OR_THROW( in_palette->size() > 0,
01157     "Invalid input palette size" );
01158 
01159   out_lut.clear();
01160 
01161   /* Extracting palette levels */
01162 
01163   std::vector< double > palette_levels;
01164   TePDIRgbPalette::iterator pal_it = in_palette->begin();
01165   TePDIRgbPalette::iterator pal_it_end = in_palette->end();
01166   
01167   unsigned int progress = 0;
01168   StartProgInt( "Building Simple Slicer Lut...", hist->size() +
01169     in_palette->size() );    
01170 
01171   while( pal_it != pal_it_end ) {
01172     UpdateProgInt( progress );
01173     
01174     palette_levels.push_back( pal_it->first );
01175 
01176     ++progress;
01177     ++pal_it;
01178   }
01179 
01180   /* min and max adjusting to the supplied histogram range */
01181 
01182   double in_hist_max = hist->GetMaxLevel();
01183   double in_hist_min = hist->GetMinLevel();
01184 
01185   min = ( min < in_hist_min ) ? in_hist_min : min;
01186   max = ( max > in_hist_max ) ? in_hist_max : max;
01187 
01188   /* Output LUT generation */
01189 
01190   double slice_size = ( max - min ) / ((double)in_palette->size());
01191 
01192   double first_pal_level = palette_levels[ 0 ];
01193   double last_pal_level = palette_levels[ palette_levels.size() - 1 ];
01194 
01195   TePDIHistogram::iterator in_hist_it = hist->begin();
01196   TePDIHistogram::iterator in_hist_it_end = hist->end();
01197 
01198   double current_level;
01199   unsigned int current_slice;
01200   
01201   while( in_hist_it != in_hist_it_end ) {
01202     UpdateProgInt( progress );
01203     
01204     current_level = in_hist_it->first;
01205 
01206     if( current_level <= min ) {
01207       out_lut[ current_level ] = first_pal_level;
01208     } else if ( current_level >= max ) {
01209       out_lut[ current_level ] = last_pal_level;
01210     } else {
01211       current_slice =
01212         (unsigned int) floor( ( current_level - min ) / slice_size );
01213         
01214       TEAGN_DEBUG_CONDITION( ( current_slice < palette_levels.size() ),
01215         "Invalid current_slice=" + Te2String( current_slice ) +
01216         " for pallete_levels size=" + Te2String( palette_levels.size() ) );
01217 
01218       out_lut[ current_level ] = palette_levels[ current_slice ];
01219     }
01220 
01221     ++progress;
01222     ++in_hist_it;
01223   }
01224 }
01225 
01226 
01227 void TePDIContrast::GetStatLut( TePDIHistogram::pointer hist,
01228   double target_mean, double target_variance, double output_channel_min_level, 
01229   double output_channel_max_level, TePDITypes::TePDILutType& out_lut )
01230 {
01231   TEAGN_CHECK_NOTEQUAL( hist->size(), 0, "Invalid histogram size" );
01232 
01233   out_lut.clear();
01234   
01235   TePDIHistogram::iterator in_hist_it;
01236   TePDIHistogram::iterator in_hist_it_end = hist->end(); 
01237   
01238   /* Calculating the total pixels number */
01239   
01240   unsigned int total_pixels = 0;
01241   
01242   in_hist_it = hist->begin();
01243   
01244   while( in_hist_it != in_hist_it_end ) {
01245     total_pixels += in_hist_it->second;
01246         
01247     ++in_hist_it;
01248   }
01249   
01250   /* Calculating the current mean */ 
01251   
01252   double current_mean = 0;
01253   
01254   if( params_.CheckParameter< double >( "input_mean" ) ) {
01255     params_.GetParameter( "input_mean", current_mean );
01256   } else {
01257     in_hist_it = hist->begin();
01258     
01259     while( in_hist_it != in_hist_it_end ) {
01260       current_mean += ( in_hist_it->first * ((double)in_hist_it->second) );
01261         
01262       ++in_hist_it;
01263     }
01264   
01265     current_mean = current_mean / ((double)total_pixels);
01266   }
01267     
01268   /* Calculating the current variance */ 
01269         
01270   double current_variance = 0;
01271   
01272   if( params_.CheckParameter< double >( "input_variance" ) ) {
01273     params_.GetParameter( "input_variance", current_variance );
01274   } else {
01275     double temp_double = 0;
01276     
01277     in_hist_it = hist->begin();
01278     
01279     while( in_hist_it != in_hist_it_end ) {
01280       temp_double = ( in_hist_it->first - current_mean );
01281       temp_double = temp_double * temp_double * ((double)in_hist_it->second);
01282       
01283       current_variance += temp_double;
01284         
01285       ++in_hist_it;
01286     }
01287     
01288     current_variance = current_variance / ( (double) total_pixels );
01289   }
01290   
01291   /* Creating levels map */
01292   
01293   double gain = sqrt( target_variance / current_variance );
01294   double offset = target_mean - ( gain * current_mean );
01295   
01296   in_hist_it = hist->begin();
01297   
01298   double current_level = 0;
01299   double mapped_level = 0;
01300   
01301   while( in_hist_it != in_hist_it_end ) {
01302     current_level = in_hist_it->first;
01303     mapped_level = ( current_level * gain ) + offset;
01304 
01305     if( mapped_level < output_channel_min_level ) {
01306       out_lut[ current_level ] = output_channel_min_level;
01307     } else if ( mapped_level > output_channel_max_level ) {
01308       out_lut[ current_level ] = output_channel_max_level;
01309     } else {
01310       out_lut[ current_level ] = mapped_level;
01311     }    
01312   
01313     ++in_hist_it;
01314   }
01315 }
01316 
01317 
01318 bool TePDIContrast::RemapLevels(
01319   TePDITypes::TePDIRasterPtrType& inRaster,
01320   TePDITypes::TePDILutType& lut,
01321   int in_channel,
01322   int out_channel,
01323   TePDITypes::TePDIRasterPtrType& outRaster,
01324   bool use_dummy, double dummy_value, bool fixed_step_lut )
01325 {
01326   TEAGN_TRUE_OR_RETURN( inRaster.isActive(),
01327     "inRaster inactive" );
01328   TEAGN_TRUE_OR_RETURN( outRaster.isActive(),
01329     "outRaster inactive" );
01330   TEAGN_TRUE_OR_RETURN( 
01331     inRaster->params().status_ != TeRasterParams::TeNotReady,
01332     "inRaster not ready" );
01333   TEAGN_TRUE_OR_RETURN( 
01334     ( outRaster->params().status_ != TeRasterParams::TeNotReady ),
01335     "outRaster not ready" );
01336     
01337   TEAGN_TRUE_OR_RETURN( ( inRaster->params().nlines_ ==
01338     outRaster->params().nlines_ ),
01339     "Lines number mismatch between input and output image" );
01340   TEAGN_TRUE_OR_RETURN( ( inRaster->params().ncols_ ==
01341     outRaster->params().ncols_ ),
01342     "Columns number mismatch between input and output image" );
01343   TEAGN_TRUE_OR_RETURN( in_channel < inRaster->nBands(), 
01344     "Invalid input band" );
01345   TEAGN_TRUE_OR_RETURN( out_channel < outRaster->nBands(), 
01346     "Invalid output band" );
01347   TEAGN_TRUE_OR_RETURN( ( lut.size() > 1 ), "Invalid lut" );
01348 
01349   const int raster_lines = inRaster->params().nlines_;
01350   const int raster_columns = inRaster->params().ncols_;
01351   
01352   /* Guessing dummy use */
01353   
01354   bool inRaster_uses_dummy = inRaster->params().useDummy_;
01355   
01356   bool outRaster_uses_dummy = outRaster->params().useDummy_;
01357   double outRaster_dummy = 0;
01358   if( outRaster_uses_dummy ) {
01359     outRaster_dummy = outRaster->params().dummy_[ out_channel ];
01360   } else {
01361     outRaster_dummy = dummy_value;
01362   }
01363   
01364   /* Loading lut */
01365   
01366   TePDIMatrix< double > lutmatrix;
01367   TEAGN_TRUE_OR_RETURN( lutmatrix.Reset( 2, lut.size(), 
01368     TePDIMatrix< double >::AutoMemPol ),
01369     "Unable to create lut matrix" );
01370   {
01371     TePDITypes::TePDILutType::iterator it = lut.begin();;
01372   
01373     for( unsigned int lutcol = 0 ; lutcol < lutmatrix.GetColumns() ; 
01374       ++lutcol ) {
01375       
01376       lutmatrix( 0, lutcol ) = it->first;
01377       lutmatrix( 1, lutcol ) = it->second;
01378       
01379       ++it;
01380     }
01381   }
01382   
01383   /* Remapping levels */
01384   
01385   StartProgInt( "Remapping Levels...", raster_lines );
01386 
01387   if( fixed_step_lut ) {
01388     double current_level = 0;
01389     const double lut_min_level = lutmatrix( 0, 0 );
01390     const double lut_max_level = lutmatrix( 0, lutmatrix.GetColumns() - 1 );
01391     unsigned int best_lut_index = 0;
01392     const unsigned int lutmatrix_last_index = ( lutmatrix.GetColumns() - 1 );
01393     
01394     double lut_step = 0;
01395     if( lutmatrix.GetColumns() > 1 ) {
01396       lut_step = lutmatrix( 0, 1 ) - lutmatrix( 0, 0 );
01397     }
01398   
01399     for( int line = 0 ; line < raster_lines ; ++line ) {
01400       TEAGN_FALSE_OR_RETURN( UpdateProgInt( line ), "Canceled by the user" );
01401     
01402       for( int column = 0 ; column < raster_columns ; ++column ) {
01403         if( inRaster->getElement( column, line, current_level,
01404             in_channel ) ) {
01405             
01406           if( use_dummy && ( current_level == dummy_value ) ) {
01407             TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01408               outRaster_dummy, out_channel ),
01409               "Level remmaping error at " + Te2String( line ) +
01410               "," + Te2String( column ) );           
01411           } else {
01412             /* Finding the mapping level from lut */
01413             
01414             if( current_level < lut_min_level ) {
01415               best_lut_index = 0;
01416             } else if( current_level > lut_max_level ) {
01417               best_lut_index = lutmatrix_last_index;
01418             } else {
01419               best_lut_index = ( unsigned int ) ( TeRound( ( current_level - 
01420                 lut_min_level ) / lut_step ) );             
01421             }
01422             
01423             /* Pixel Output level remapping */
01424             
01425             TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01426               lutmatrix( 1, best_lut_index ), out_channel ),
01427               "Level remmaping error at " + Te2String( line ) +
01428               "," + Te2String( column ) );
01429           }
01430         } else {
01431           TEAGN_TRUE_OR_RETURN( inRaster_uses_dummy, "Raster read error" );
01432             
01433           TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01434             outRaster_dummy, out_channel ),
01435             "Level remmaping error at " + Te2String( line ) +
01436             "," + Te2String( column ) );          
01437         }
01438       }
01439     }
01440   } else {
01441     double current_level;
01442     unsigned int left_element_index;
01443     unsigned int middle_element_index;
01444     unsigned int right_element_index;
01445     const unsigned int last_valid_index = lutmatrix.GetColumns() - 1;
01446     const unsigned int lut_size = lutmatrix.GetColumns();
01447     double middle_element_level;
01448   
01449     for( int line = 0 ; line < raster_lines ; ++line ) {
01450       TEAGN_FALSE_OR_RETURN( UpdateProgInt( line ), "Canceled by the user" );
01451     
01452       for( int column = 0 ; column < raster_columns ; ++column ) {
01453         if( inRaster->getElement( column, line, current_level,
01454             in_channel ) ) {
01455             
01456           if( use_dummy && ( current_level == dummy_value ) ) {
01457             TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01458               outRaster_dummy, out_channel ),
01459               "Level remmaping error at " + Te2String( line ) +
01460               "," + Te2String( column ) );           
01461           } else {            
01462             /* Finding the two best mapping levels from lut */
01463             
01464             if( lut_size == 1 ) {
01465               right_element_index = left_element_index = 1;
01466             } else {
01467               left_element_index = 0;
01468               right_element_index = last_valid_index;
01469             
01470               do {
01471                 middle_element_index =  left_element_index + 
01472                   ( ( right_element_index - left_element_index ) / 2 );
01473                 middle_element_level = lutmatrix( 0, middle_element_index );
01474                           
01475                 if( current_level == middle_element_level ) {
01476                   left_element_index = right_element_index = 
01477                     middle_element_index;
01478                   break;
01479                 } else if( current_level < middle_element_level ) {
01480                   right_element_index = middle_element_index;
01481                 } else {
01482                   left_element_index = middle_element_index;
01483                 }          
01484               } while( ( right_element_index - left_element_index ) > 1 );
01485             }
01486             
01487             /* Pixel Output level aproximation and mapping */
01488             
01489             if( ( current_level - lutmatrix( 0, left_element_index ) ) <
01490                 ( lutmatrix( 0, right_element_index ) - current_level ) ) {
01491     
01492               TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01493                 lutmatrix( 1, left_element_index ), out_channel ),
01494                 "Level remmaping error at " + Te2String( line ) +
01495                 "," + Te2String( column ) );
01496             } else {
01497               TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01498                 lutmatrix( 1, right_element_index ), out_channel ),
01499                 "Level remmaping error at " + Te2String( line ) +
01500                 "," + Te2String( column ) );
01501             }
01502           }
01503         } else {
01504           TEAGN_TRUE_OR_RETURN( inRaster_uses_dummy, "Raster read error" );
01505           
01506           TEAGN_TRUE_OR_RETURN( outRaster->setElement( column, line,
01507             outRaster_dummy, out_channel ),
01508             "Level remmaping error at " + Te2String( line ) +
01509             "," + Te2String( column ) );          
01510         }
01511       }
01512     }
01513   }
01514   
01515   StopProgInt();
01516   
01517   return true;
01518 }
01519 
01520 
01521 bool TePDIContrast::FullRangeLutRemapLevels( 
01522   TePDITypes::TePDIRasterPtrType& inRaster, TePDITypes::TePDILutType& lut,
01523   int in_channel, int out_channel, TePDITypes::TePDIRasterPtrType& outRaster, 
01524   bool use_dummy, double dummy_value )
01525 {
01526   TEAGN_TRUE_OR_RETURN( inRaster.isActive(),
01527     "inRaster inactive" );
01528   TEAGN_TRUE_OR_RETURN( outRaster.isActive(),
01529     "outRaster inactive" );
01530   TEAGN_TRUE_OR_RETURN( 
01531     inRaster->params().status_ != TeRasterParams::TeNotReady,
01532     "inRaster not ready" );
01533   TEAGN_TRUE_OR_RETURN( 
01534     ( outRaster->params().status_ != TeRasterParams::TeNotReady ),
01535     "outRaster not ready" );
01536     
01537   TEAGN_TRUE_OR_RETURN( ( inRaster->params().nlines_ ==
01538     outRaster->params().nlines_ ),
01539     "Lines number mismatch between input and output image" );
01540   TEAGN_TRUE_OR_RETURN( ( inRaster->params().ncols_ ==
01541     outRaster->params().ncols_ ),
01542     "Columns number mismatch between input and output image" );
01543   TEAGN_TRUE_OR_RETURN( in_channel < inRaster->nBands(), 
01544     "Invalid input band" );
01545   TEAGN_TRUE_OR_RETURN( out_channel < outRaster->nBands(), 
01546     "Invalid output band" );
01547   TEAGN_TRUE_OR_RETURN( ( lut.size() > 1 ), "Invalid lut" );
01548 
01549   const int raster_lines = inRaster->params().nlines_;
01550   const int raster_columns = inRaster->params().ncols_;
01551   
01552   /* Guessing dummy use */
01553   
01554   bool inRaster_uses_dummy = inRaster->params().useDummy_;
01555   
01556   bool outRaster_uses_dummy = outRaster->params().useDummy_;
01557   double outRaster_dummy = 0;
01558   if( outRaster_uses_dummy ) {
01559     outRaster_dummy = outRaster->params().dummy_[ out_channel ];
01560   } else {
01561     outRaster_dummy = dummy_value;
01562   }
01563   
01564   /* Loading lut */
01565   
01566   TePDIMatrix< double > lutmatrix;
01567   TEAGN_TRUE_OR_RETURN( lutmatrix.Reset( 2, lut.size(), 
01568     TePDIMatrix< double >::AutoMemPol ),
01569     "Unable to create lut matrix" );
01570   {
01571     TePDITypes::TePDILutType::iterator it = lut.begin();;
01572   
01573     for( unsigned int lutcol = 0 ; lutcol < lutmatrix.GetColumns() ; 
01574       ++lutcol ) {
01575       
01576       lutmatrix( 0, lutcol ) = it->first;
01577       lutmatrix( 1, lutcol ) = it->second;
01578       
01579       ++it;
01580     }
01581   }
01582   
01583   /* Remapping levels */
01584   
01585   TeRaster& inRaster_ref = *inRaster;
01586   TeRaster& outRaster_ref = *outRaster;
01587   int line = 0;
01588   int column = 0 ;
01589   double current_level = 0;
01590   
01591   StartProgInt( "Remapping Levels...", raster_lines );
01592   
01593   for( line = 0 ; line < raster_lines ; ++line ) {
01594     TEAGN_FALSE_OR_RETURN( UpdateProgInt( line ), "Canceled by the user" );
01595     
01596     for( column = 0 ; column < raster_columns ; ++column ) {
01597       if( inRaster_ref.getElement( column, line, current_level,
01598         in_channel ) ) { 
01599         
01600         if( use_dummy && ( current_level == dummy_value ) ) {
01601           TEAGN_TRUE_OR_RETURN( outRaster_ref.setElement( column, line,
01602             outRaster_dummy, out_channel ),
01603             "Level remmaping error at " + Te2String( line ) +
01604             "," + Te2String( column ) );       
01605         } else {
01606           TEAGN_DEBUG_CONDITION( ( ( (unsigned int)current_level ) <
01607             lutmatrix.GetColumns() ), "Level out of lut range" );
01608           TEAGN_DEBUG_CONDITION( 
01609             ( lutmatrix( 0, ( (unsigned int)current_level ) ) ==
01610             ( (unsigned int)current_level ) ), 
01611             "Requested value not found inside lut" );
01612           
01613           TEAGN_TRUE_OR_RETURN( outRaster_ref.setElement( column, line,
01614             lutmatrix( 1, ( (unsigned int)current_level ) ), out_channel ),
01615             "Level remmaping error at " + Te2String( line ) +
01616             "," + Te2String( column ) );          
01617         }
01618       } else {
01619         TEAGN_TRUE_OR_RETURN( inRaster_uses_dummy, "Raster read error" );
01620             
01621         TEAGN_TRUE_OR_RETURN( outRaster_ref.setElement( column, line,
01622           outRaster_dummy, out_channel ),
01623           "Level remmaping error at " + Te2String( line ) +
01624           "," + Te2String( column ) );       
01625       }
01626     }
01627   }
01628   
01629   StopProgInt();
01630   
01631   return true;  
01632 }
01633 
01634 
01635 bool TePDIContrast::getHistogram( TePDIHistogram::pointer& hist,
01636   bool useDummy, double dummyValue )
01637 {
01638   if( ! histo_ptr_.isActive() ) {
01639     if( params_.CheckParameter< TePDIHistogram::pointer >( 
01640       "input_histogram" ) ) {
01641     
01642       params_.GetParameter( "input_histogram", histo_ptr_ );
01643     } else {
01644       /* No histogram supplied, we need to generate it */
01645   
01646       TePDITypes::TePDIRasterPtrType inRaster;
01647       TEAGN_TRUE_OR_RETURN( params_.GetParameter( "input_image", inRaster ),
01648         "Missing parameter : input_image" );
01649       
01650       int input_band = 0;
01651       TEAGN_TRUE_OR_RETURN( params_.GetParameter( "input_band", input_band ),
01652         "Missing parameter : input_band" );
01653       
01654       int histo_levels = 0;
01655       if( ( inRaster->params().dataType_[ input_band ] == TeFLOAT ) ||
01656         ( inRaster->params().dataType_[ input_band ] == TeDOUBLE ) ) {
01657         
01658         histo_levels = 256;
01659       }
01660       if( params_.CheckParameter< int >( "histo_levels" ) ) {
01661         params_.GetParameter( "histo_levels", histo_levels );
01662       }
01663       
01664       histo_ptr_.reset( new TePDIHistogram );
01665       TEAGN_TRUE_OR_RETURN( 
01666         histo_ptr_->reset( inRaster, input_band, 
01667         (unsigned int)histo_levels, 
01668         TeBoxPixelIn ), "Histogram generation error" );
01669         
01670       // Removing the dummy value from the generated histrogram
01671       
01672       if( useDummy )
01673       {
01674         histo_ptr_->erase( dummyValue );
01675       }
01676     }
01677   }
01678   
01679   hist = histo_ptr_;
01680   
01681   return true;
01682 }
01683 
01684 bool TePDIContrast::getBaseLut( TePDITypes::TePDILutType& lut,
01685   bool& hist_based_lut, bool useDummy, double dummyValue )
01686 {
01687   lut.clear();
01688   
01689   if( params_.CheckParameter< TePDIHistogram::pointer >( 
01690     "input_histogram" ) ) 
01691   {
01692   
01693     TePDIHistogram::pointer hist;
01694     TEAGN_TRUE_OR_RETURN( getHistogram( hist, useDummy, dummyValue ), 
01695       "Unable to get histogram" );    
01696     
01697     TePDIHistogram::iterator it = hist->begin();
01698     TePDIHistogram::iterator it_end = hist->end();
01699       
01700     while( it != it_end ) {
01701       lut[ it->first ] = it->first;
01702     
01703       ++it;
01704     }
01705       
01706     hist_based_lut = true;    
01707   } else {
01708     TePDITypes::TePDIRasterPtrType inRaster;
01709     params_.GetParameter( "input_image", inRaster );
01710     
01711     int input_band = 0;
01712     params_.GetParameter( "input_band", input_band );
01713       
01714     switch( inRaster->params().dataType_[ input_band ] ) {
01715       case TeBIT :
01716       case TeUNSIGNEDCHAR :
01717       case TeUNSIGNEDSHORT :
01718       {
01719         unsigned int lut_size = (unsigned int)( 
01720           pow( 2.0, (double)( inRaster->params().elementSize( input_band ) * 
01721           8 ) ) );
01722       
01723         for( unsigned int index = 0 ; index < lut_size ; ++index ) {
01724           lut[ index ] = index;
01725         }
01726             
01727         hist_based_lut = false;
01728         
01729         break;
01730       }
01731       case TeCHAR :
01732       case TeSHORT :      
01733       case TeINTEGER :
01734       case TeLONG :
01735       case TeUNSIGNEDLONG :
01736       case TeFLOAT :
01737       case TeDOUBLE :
01738       {
01739         TePDIHistogram::pointer hist;
01740         TEAGN_TRUE_OR_RETURN( getHistogram( hist, useDummy, dummyValue ), 
01741           "Unable to get histogram" );
01742         
01743         TePDIHistogram::iterator it = hist->begin();
01744         TePDIHistogram::iterator it_end = hist->end();
01745         
01746         while( it != it_end ) {
01747           lut[ it->first ] = it->first;
01748       
01749           ++it;
01750         }
01751         
01752         hist_based_lut = true;
01753         
01754         break;
01755       }
01756       default :
01757       {
01758         TEAGN_LOG_AND_THROW( "Invalid raster pixel type" );
01759         break;
01760       }
01761     }
01762   }
01763   
01764   return true;
01765 }
01766 

Generated on Sun Jul 29 04:01:23 2012 for TerraLib - Development Source by  doxygen 1.5.3