"Fossies" - the Fresh Open Source Software Archive

Member "pfstools-2.2.0/src/tmo/fattal02/pfstmo_fattal02.cpp" (12 Aug 2021, 8358 Bytes) of package /linux/privat/pfstools-2.2.0.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /**
    2  * @file pfstmo_fattal02.cpp
    3  * @brief Tone map XYZ channels using Fattal02 model
    4  *
    5  * Gradient Domain High Dynamic Range Compression
    6  * R. Fattal, D. Lischinski, and M. Werman
    7  * In ACM Transactions on Graphics, 2002.
    8  *
    9  * 
   10  * This file is a part of PFSTMO package.
   11  * ---------------------------------------------------------------------- 
   12  * Copyright (C) 2003,2004 Grzegorz Krawczyk
   13  * 
   14  *  This program is free software; you can redistribute it and/or modify
   15  *  it under the terms of the GNU General Public License as published by
   16  *  the Free Software Foundation; either version 2 of the License, or
   17  *  (at your option) any later version.
   18  *
   19  *  This program is distributed in the hope that it will be useful,
   20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22  *  GNU General Public License for more details.
   23  *
   24  *  You should have received a copy of the GNU General Public License
   25  *  along with this program; if not, write to the Free Software
   26  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   27  * ---------------------------------------------------------------------- 
   28  * 
   29  * @author Grzegorz Krawczyk, <krawczyk@mpi-sb.mpg.de>
   30  *
   31  * $Id: pfstmo_fattal02.cpp,v 1.10 2012/06/22 12:01:32 rafm Exp $
   32  */
   33 
   34 #include <config.h>
   35 
   36 #include <iostream>
   37 #include <stdio.h>
   38 #include <stdlib.h>
   39 #include <getopt.h>
   40 #include <math.h>
   41 
   42 #include <pfs.h>
   43 
   44 #include <algorithm>
   45 
   46 #include "tmo_fattal02.h"
   47 
   48 using namespace std;
   49 
   50 #define PROG_NAME "pfstmo_fattal02"
   51 
   52 /// verbose mode
   53 bool verbose = false;
   54 
   55 class QuietException 
   56 {
   57 };
   58 
   59 void printHelp()
   60 {
   61   fprintf( stderr, PROG_NAME " (" PACKAGE_STRING ") : \n"
   62     "\t[--alpha <val>] [--beta <val>] \n"
   63     "\t[--gamma <val>] \n"
   64     "\t[--saturation <val>] \n"
   65     "\t[--noise <val>] \n"
   66     "\t[--detail-level <val>] \n"
   67     "\t[--black-point <val>] [--white-point <val>] \n"
   68     "\t[--multigrid] \n"
   69     "\t[--verbose] [--help] \n"
   70     "See man page for more information.\n" );
   71 }
   72 
   73 void pfstmo_fattal02( int argc, char* argv[] )
   74 {
   75   pfs::DOMIO pfsio;
   76 
   77   //--- default tone mapping parameters;
   78   float opt_alpha = 1.0f;
   79   float opt_beta = 0.9f;
   80   float opt_gamma = -1.0f;    // not set (0.8 for fft solver, 1.0 otherwise)
   81   float opt_saturation=0.8f;
   82   float opt_noise = -1.0f;    // not set 
   83   int   opt_detail_level=-1;  // not set (2 for fft solver, 0 otherwise)
   84   float opt_black_point=0.1f;
   85   float opt_white_point=0.5f;
   86 
   87   // Use multigrid if FFTW lib not available
   88 #if !defined(HAVE_FFTW3) || !defined(HAVE_OpenMP)
   89   bool  opt_fftsolver=false;
   90 #else  
   91   bool  opt_fftsolver=true;
   92 #endif
   93   
   94   static struct option cmdLineOptions[] = {
   95     { "help", no_argument, NULL, 'h' },
   96     { "verbose", no_argument, NULL, 'v' },
   97     { "multigrid", no_argument, NULL, 'm' },
   98     { "alpha", required_argument, NULL, 'a' },
   99     { "beta", required_argument, NULL, 'b' },
  100     { "gamma", required_argument, NULL, 'g' },
  101     { "saturation", required_argument, NULL, 's' },
  102     { "noise", required_argument, NULL, 'n' },
  103     { "detail-level", required_argument, NULL, 'd' },
  104     { "white-point", required_argument, NULL, 'w' },
  105     { "black-point", required_argument, NULL, 'l' },
  106     { NULL, 0, NULL, 0 }
  107   };
  108 
  109   int optionIndex = 0;
  110   while( 1 ) {
  111     int c = getopt_long (argc, argv, "hvma:b:g:s:n:d:w:k:", cmdLineOptions, &optionIndex);
  112     if( c == -1 ) break;
  113     switch( c ) {
  114     case 'h':
  115       printHelp();
  116       throw QuietException();
  117     case 'v':
  118       verbose = true;
  119       break;
  120     case 'm':
  121       opt_fftsolver = false;
  122       break;
  123     case 'a':
  124       opt_alpha = (float)strtod( optarg, NULL );
  125       if( opt_alpha<=0.0f )
  126         throw pfs::Exception("alpha value out of range, should be >0");
  127       break;
  128     case 'b':
  129       opt_beta = (float)strtod( optarg, NULL );
  130       if( opt_beta<=0.0f )
  131         throw pfs::Exception("beta value out of range, should be >0");
  132       break;
  133     case 'g':
  134       opt_gamma = (float)strtod( optarg, NULL );
  135       if( opt_gamma<=0.0f || opt_gamma>=10.0 )
  136         throw pfs::Exception("gamma value out of range, should be >0");
  137       break;
  138     case 's':
  139       opt_saturation = (float)strtod( optarg, NULL );
  140       if( opt_saturation<=0.0f || opt_saturation>1.0f )
  141         throw pfs::Exception("saturation value out of range, should be 0..1");
  142       break;
  143     case 'n':
  144       opt_noise = (float)strtod( optarg, NULL );
  145       if( opt_noise<0.0f )
  146         throw pfs::Exception("noise level value out of range, should be >=0");
  147       break;
  148     case 'd':
  149       opt_detail_level = (int) strtod( optarg, NULL );
  150       if( opt_detail_level<0 || opt_detail_level>9 )
  151         throw pfs::Exception("detail-level value out of range, should be 0..9");
  152       break;
  153     case 'w':
  154       opt_white_point = (float)strtod( optarg, NULL );
  155       if( opt_white_point<0.0f || opt_white_point>=50.0f )
  156         throw pfs::Exception("white-point value out of range, should be 0..50");
  157       break;
  158     case 'k':
  159       opt_black_point = (float)strtod( optarg, NULL );
  160       if( opt_black_point<0.0f || opt_black_point>=50.0f )
  161         throw pfs::Exception("black-point value out of range, should be 0..50");
  162       break;
  163     case '?':
  164       throw QuietException();
  165     case ':':
  166       throw QuietException();
  167     }
  168   }
  169 
  170   if( opt_fftsolver ) {
  171     // Default params for the fftsolver
  172     if(opt_detail_level==-1)
  173       opt_detail_level=3;     // 2 for low res, 3 is better for high res
  174     if(opt_gamma==-1.0f)
  175       opt_gamma=0.8f;
  176     if(opt_noise==-1.0f)
  177       opt_noise=0.002f;
  178   }
  179 
  180   
  181   // adjust noise floor if not set by user
  182   if( opt_noise<0.0f )
  183     opt_noise = opt_alpha*0.01;
  184   // set gamma and detail level to default values which produce the
  185   // same output as older programme versions using the multi-level pde solver
  186   if(opt_detail_level==-1)
  187     opt_detail_level=0;
  188   if(opt_gamma==-1.0f)
  189     opt_gamma=1.0f;
  190 
  191   VERBOSE_STR << "threshold gradient (alpha): " << opt_alpha << endl;
  192   VERBOSE_STR << "strengh of modification (beta): " << opt_beta << endl;
  193   VERBOSE_STR << "gamma: " << opt_gamma << endl;
  194   VERBOSE_STR << "noise floor: " << opt_noise << endl;  
  195   VERBOSE_STR << "saturation: " << opt_saturation << endl;
  196   VERBOSE_STR << "detail level: " << opt_detail_level << endl;
  197   VERBOSE_STR << "white point: " << opt_white_point << "%" << endl;
  198   VERBOSE_STR << "black point: " << opt_black_point << "%" << endl;
  199   VERBOSE_STR << "use fft pde solver: " << opt_fftsolver << endl;
  200 
  201   while( true ) 
  202   {
  203     pfs::Frame *frame = pfsio.readFrame( stdin );
  204     if( frame == NULL ) break; // No more frames
  205 
  206     pfs::Channel *X, *Y, *Z;
  207     frame->getXYZChannels( X, Y, Z );
  208     frame->getTags()->setString("LUMINANCE", "RELATIVE");
  209     //---
  210 
  211     if( Y==NULL || X==NULL || Z==NULL)
  212       throw pfs::Exception( "Missing X, Y, Z channels in the PFS stream" );
  213         
  214     // tone mapping
  215     int w = Y->getCols();
  216     int h = Y->getRows();
  217 
  218     pfs::Array2DImpl* L = new pfs::Array2DImpl(w,h);
  219     tmo_fattal02(w, h, Y->getRawData(), L->getRawData(), opt_alpha, opt_beta,
  220             opt_gamma, opt_noise, opt_detail_level,
  221             opt_black_point, opt_white_point, opt_fftsolver);
  222 
  223     // in-place color space transform
  224     pfs::Array2DImpl *G = new pfs::Array2DImpl( w, h ); // copy for G to preserve Y
  225     pfs::Array2D *R = X, *B = Z;
  226     pfs::transformColorSpace( pfs::CS_XYZ, X, Y, Z, pfs::CS_RGB, R, G, B );
  227     
  228     // Color correction 
  229     for( int i=0; i < w*h; i++ )
  230     {
  231       const float epsilon = 1e-4f;
  232       float y = std::max( (*Y)(i), epsilon );
  233       float l = std::max( (*L)(i), epsilon );
  234       (*R)(i) = powf( std::max((*R)(i)/y,0.f), opt_saturation ) * l;      
  235       (*G)(i) = powf( std::max((*G)(i)/y,0.f), opt_saturation ) * l;
  236       (*B)(i) = powf( std::max((*B)(i)/y,0.f), opt_saturation ) * l;
  237     }
  238     
  239     
  240     pfs::transformColorSpace( pfs::CS_RGB, R, G, B, pfs::CS_XYZ, X, Y, Z );
  241 
  242     delete G;    
  243     delete L;
  244     
  245     //---
  246     pfsio.writeFrame( frame, stdout );
  247     pfsio.freeFrame( frame );        
  248   }
  249 }
  250 
  251 int main( int argc, char* argv[] )
  252 {
  253   try {
  254     pfstmo_fattal02( argc, argv );
  255   }
  256   catch( pfs::Exception ex ) {
  257     fprintf( stderr, PROG_NAME " error: %s\n", ex.getMessage() );
  258     return EXIT_FAILURE;
  259   }        
  260   catch( QuietException  ex ) {
  261     return EXIT_FAILURE;
  262   }        
  263   return EXIT_SUCCESS;
  264 }