/** * @file pfstmo_pattanaik00.cpp * @brief Tone map XYZ channels using Pattanaik00 model * * Time-Dependent Visual Adaptation for Realistic Image Display * S.N. Pattanaik, J. Tumblin, H. Yee, and D.P. Greenberg * In Proceedings of ACM SIGGRAPH 2000 * * * This file is a part of PFSTMO package. * ---------------------------------------------------------------------- * Copyright (C) 2003,2004 Grzegorz Krawczyk * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------- * * @author Grzegorz Krawczyk, * * $Id: pfstmo_pattanaik00.cpp,v 1.1 2007/06/14 10:57:50 gkrawczyk Exp $ */ #include #include #include #include #include #include #include #include using namespace std; #define PROG_NAME "pfstmo_pattanaik00" class QuietException { }; void multiplyChannels( pfs::Array2D* X, pfs::Array2D* Y, pfs::Array2D* Z, float mult ); void printHelp() { fprintf( stderr, PROG_NAME " (" PACKAGE_STRING ") : \n" "\t[--time-dependence] [--local] \n" "\t[--mul ] \n" "\t[--cone ] [--rod ] \n" "\t[--verbose] [--help]\n" "See man page for more information.\n" ); } void pfstmo_pattanaik00( int argc, char* argv[] ) { pfs::DOMIO pfsio; //--- default tone mapping parameters; bool timedependence = false; bool local = false; float multiplier = 1.0f; float Acone = -1.0f; float Arod = -1.0f; float fps = 16.0f; //--- process command line args bool verbose = false; static struct option cmdLineOptions[] = { { "help", no_argument, NULL, 'h' }, { "verbose", no_argument, NULL, 'v' }, { "time-dependence", no_argument, NULL, 't' }, { "fps", required_argument, NULL, 'f' }, { "local", no_argument, NULL, 'l' }, { "mul", required_argument, NULL, 'm' }, { "cone", required_argument, NULL, 'c' }, { "rod", required_argument, NULL, 'r' }, { NULL, 0, NULL, 0 } }; int optionIndex = 0; while( 1 ) { int c = getopt_long (argc, argv, "hvtf:lm:c:r:", cmdLineOptions, &optionIndex); if( c == -1 ) break; switch( c ) { case 'h': printHelp(); throw QuietException(); case 'v': verbose = true; break; case 't': timedependence = true; break; case 'l': local = true; break; case 'f': fps = (float)strtod( optarg, NULL ); if( fps<=0.0f ) throw pfs::Exception("incorrect frames per second value, should be non-zero positive"); break; case 'm': multiplier = (float)strtod( optarg, NULL ); if( multiplier<=0.0f ) throw pfs::Exception("incorrect multiplier value, should be non-zero positive"); break; case 'c': Acone = (float)strtod( optarg, NULL ); if( Acone<=0.0f ) throw pfs::Exception("incorrect cone adaptation value, should be non-zero positive"); if( Arod==-1.0f ) Arod=Acone; break; case 'r': Arod = (float)strtod( optarg, NULL ); if( Arod<=0.0f ) throw pfs::Exception("incorrect rod adaptation value, should be non-zero positive"); break; case '?': throw QuietException(); case ':': throw QuietException(); } } VERBOSE_STR << "time-dependence: " << (timedependence ? "yes" : "no") << endl; if( timedependence ) VERBOSE_STR << "frames per sec.: " << fps << endl; VERBOSE_STR << "local: " << (local ? "yes" : "no") << endl; VERBOSE_STR << "multiplier: " << multiplier << endl; VisualAdaptationModel* am = new VisualAdaptationModel(); bool firstFrame = true; while( true ) { pfs::Frame *frame = pfsio.readFrame( stdin ); if( frame == NULL ) break; // No more frames pfs::Channel *X, *Y, *Z; frame->getXYZChannels( X, Y, Z ); frame->getTags()->setString("LUMINANCE", "RELATIVE"); //--- if( Y==NULL || X==NULL || Z==NULL) throw pfs::Exception( "Missing X, Y, Z channels in the PFS stream" ); // adaptation model if( multiplier!=1.0f ) multiplyChannels( X, Y, Z, multiplier ); if( !local ) { if( firstFrame || !timedependence ) { if( Acone!=-1.0f ) am->setAdaptation(Acone,Arod); else am->setAdaptation(Y); } else am->calculateAdaptation(Y, 1.0f/fps); VERBOSE_STR << "adaptation cone: " << am->getAcone() << endl; VERBOSE_STR << "adaptation rod: " << am->getArod() << endl; VERBOSE_STR << "bleaching cone: " << am->getBcone() << endl; VERBOSE_STR << "bleaching rod: " << am->getBrod() << endl; } // tone mapping int w = Y->getCols(); int h = Y->getRows(); pfs::Array2D* R = new pfs::Array2DImpl(w,h); pfs::Array2D* G = new pfs::Array2DImpl(w,h); pfs::Array2D* B = new pfs::Array2DImpl(w,h); pfs::transformColorSpace( pfs::CS_XYZ, X, Y, Z, pfs::CS_RGB, R, G, B ); tmo_pattanaik00( R, G, B, Y, am, local ); pfs::transformColorSpace( pfs::CS_RGB, R, G, B, pfs::CS_XYZ, X, Y, Z ); delete R; delete G; delete B; //--- pfsio.writeFrame( frame, stdout ); pfsio.freeFrame( frame ); } delete am; // delete visual adaptation model } void multiplyChannels( pfs::Array2D* X, pfs::Array2D* Y, pfs::Array2D* Z, float mult ) { int size = Y->getCols() * Y->getRows(); for( int i=0 ; i