1 /**
2  * @file pfstmo_ferradans11.cpp
3  * @brief Tone map RGB channels using Ferradans11 model
4  *
5  * An Analysis of Visual Adaptation and Contrast Perception for Tone Mapping
6  * S. Ferradans, M. Bertalmio, E. Provenzi, V. Caselles
7  * In IEEE Trans. Pattern Analysis and Machine Intelligence 2011
8  *
9  *
10  * This file is a part of PFSTMO package.
11  * ----------------------------------------------------------------------
12  * Copyright (C) 2013 Sira Ferradans
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 Sira Ferradans,
30  *
31  */
32 
33 #include <stdlib.h>
34 
35 #include <getopt.h>
36 #include <pfs.h>
37 #include "pfstmo.h"
38 
39 #include "Imagen.h"
40 
41 #define PROG_NAME "pfstmo_ferradans11"
42 
43 /// verbose mode
44 bool verbose = false;
45 
46 class QuietException
47 {
48 };
49 
printHelp()50 void printHelp()
51 {
52   fprintf( stderr, PROG_NAME " (" PACKAGE_STRING ") : \n"
53     "\t[--rho <val>] controls the overall intensity of the final output, the bigger the value the darker the image. Its range is approx (-10,10), recommended 0, although it might depend on the image. \n"
54     "\t[--inv_alpha <val>] related to the contrast resolution. The bigger the more local contrast. For a good constrast resolution we suggest the value 20. Valid values:(0.1,100)\n"
55     "See man page for more information.\n" );
56 }
57 
pfstmo_ferradans11(int argc,char * argv[])58 void pfstmo_ferradans11( int argc, char* argv[] )
59 {
60   pfs::DOMIO pfsio;
61 
62   //--- default tone mapping parameters;
63   float rho = -2;
64   float inv_alpha = 5;
65 
66 
67   static struct option cmdLineOptions[] = {
68     { "help", no_argument, NULL, 'h' },
69     { "rho", required_argument, NULL, 'r' },
70     { "inv_alpha", required_argument, NULL, 'a' },
71     { NULL, 0, NULL, 0 }
72   };
73 
74   static const char optstring[] = "hr:a:";
75 
76   int optionIndex = 0;
77   while( 1 ) {
78       int c = getopt_long (argc, argv, optstring, cmdLineOptions, &optionIndex);
79 
80 
81 
82       if( c == -1 ){ break;}
83 
84     switch( c ) {
85     case 'h':
86       printHelp();
87       throw QuietException();
88     case 'v':
89       verbose = true;
90       break;
91     case 'r':
92       rho = (float)strtod( optarg, NULL );
93       break;
94     case 'a':
95       inv_alpha = (float)strtod( optarg, NULL );
96       if( inv_alpha<=0.0f )
97         throw pfs::Exception("inv_alpha value out of range, should be >0");
98       break;
99    case '?':
100       printHelp();
101       throw QuietException();
102 
103    case ':':
104       printHelp();
105       throw QuietException();
106 
107    }
108   }
109 
110   while( true )
111   {
112     pfs::Frame *frame = pfsio.readFrame( stdin );
113     if( frame == NULL ) break; // No more frames
114 
115     pfs::Channel *X, *Y, *Z;
116     frame->getXYZChannels( X, Y, Z );
117     frame->getTags()->setString("LUMINANCE", "RELATIVE");
118     //---
119 
120     if( Y==NULL || X==NULL || Z==NULL)
121       throw pfs::Exception( "Missing X, Y, Z channels in the PFS stream" );
122 
123     // tone mapping
124       int w = Z->getCols();
125       int h = Z->getRows();
126 
127     // in-place color space transform
128       pfs::Array2DImpl* R = new pfs::Array2DImpl(w,h);
129       pfs::Array2DImpl* G = new pfs::Array2DImpl(w,h);
130       pfs::Array2DImpl* B = new pfs::Array2DImpl(w,h);
131 
132       pfs::transformColorSpace( pfs::CS_XYZ, X, Y, Z, pfs::CS_RGB, R, G, B );
133 
134       tmo_ferradans11(w, h, R->getRawData(), G->getRawData(), B->getRawData(),
135                       rho, inv_alpha);
136 
137       pfs::transformColorSpace( pfs::CS_SRGB, R, G, B, pfs::CS_XYZ, X, Y, Z );
138 
139       delete R;
140       delete G;
141       delete B;
142 
143       //---
144 
145       pfsio.writeFrame( frame, stdout );
146       pfsio.freeFrame( frame );
147 
148   }
149 }
150 
main(int argc,char * argv[])151 int main( int argc, char* argv[] )
152 {
153   try {
154     pfstmo_ferradans11( argc, argv );
155   }
156   catch( pfs::Exception ex ) {
157     fprintf( stderr, PROG_NAME " error: %s\n", ex.getMessage() );
158     return EXIT_FAILURE;
159   }
160   catch( QuietException  ex ) {
161     return EXIT_FAILURE;
162   }
163   return EXIT_SUCCESS;
164 }
165