00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "fleximage.h"
00029 #include "error.h"
00030 #include "scene.h"
00031 #include "filter.h"
00032 #include "exrio.h"
00033 #include "tgaio.h"
00034 #include "pngio.h"
00035 #include "blackbodyspd.h"
00036 #include "osfunc.h"
00037 #include "dynload.h"
00038
00039 #include <iostream>
00040 #include <fstream>
00041
00042 #include <boost/thread/xtime.hpp>
00043 #include <boost/archive/text_oarchive.hpp>
00044 #include <boost/archive/text_iarchive.hpp>
00045 #include <boost/archive/binary_oarchive.hpp>
00046 #include <boost/archive/binary_iarchive.hpp>
00047 #include <boost/serialization/split_member.hpp>
00048 #include <boost/serialization/vector.hpp>
00049 #include <boost/serialization/string.hpp>
00050 #include <boost/iostreams/filtering_stream.hpp>
00051 #include <boost/iostreams/filtering_streambuf.hpp>
00052 #include <boost/iostreams/copy.hpp>
00053 #include <boost/iostreams/filter/zlib.hpp>
00054 #include <boost/iostreams/filter/bzip2.hpp>
00055 #include <boost/iostreams/filter/gzip.hpp>
00056
00057 using namespace boost::iostreams;
00058 using namespace lux;
00059
00060
00061 FlexImageFilm::FlexImageFilm(int xres, int yres, Filter *filt, const float crop[4],
00062 const string &filename1, bool premult, int wI, int dI, int cM,
00063 bool cw_EXR, OutputChannels cw_EXR_channels, bool cw_EXR_halftype, int cw_EXR_compressiontype, bool cw_EXR_applyimaging,
00064 bool cw_EXR_gamutclamp, bool cw_EXR_ZBuf, ZBufNormalization cw_EXR_ZBuf_normalizationtype,
00065 bool cw_PNG, OutputChannels cw_PNG_channels, bool cw_PNG_16bit, bool cw_PNG_gamutclamp, bool cw_PNG_ZBuf, ZBufNormalization cw_PNG_ZBuf_normalizationtype,
00066 bool cw_TGA, OutputChannels cw_TGA_channels, bool cw_TGA_gamutclamp, bool cw_TGA_ZBuf, ZBufNormalization cw_TGA_ZBuf_normalizationtype,
00067 bool w_resume_FLM, bool restart_resume_FLM, int haltspp, int halttime,
00068 int p_TonemapKernel, float p_ReinhardPreScale, float p_ReinhardPostScale,
00069 float p_ReinhardBurn, float p_LinearSensitivity, float p_LinearExposure, float p_LinearFStop, float p_LinearGamma,
00070 float p_ContrastYwa, float p_Gamma,
00071 const float cs_red[2], const float cs_green[2], const float cs_blue[2], const float whitepoint[2],
00072 int reject_warmup, bool debugmode) :
00073 Film(xres, yres, haltspp, halttime), filter(filt), writeInterval(wI), displayInterval(dI),
00074 filename(filename1), premultiplyAlpha(premult), buffersInited(false),
00075 writeResumeFlm(w_resume_FLM), restartResumeFlm(restart_resume_FLM),
00076 framebuffer(NULL), debug_mode(debugmode),
00077 colorSpace(cs_red[0], cs_red[1], cs_green[0], cs_green[1], cs_blue[0], cs_blue[1], whitepoint[0], whitepoint[1], 1.f)
00078 {
00079
00080 memcpy(cropWindow, crop, 4 * sizeof(float));
00081 xPixelStart = Ceil2Int(xResolution * cropWindow[0]);
00082 xPixelCount = max(1, Ceil2Int(xResolution * cropWindow[1]) - xPixelStart);
00083 yPixelStart = Ceil2Int(yResolution * cropWindow[2]);
00084 yPixelCount = max(1, Ceil2Int(yResolution * cropWindow[3]) - yPixelStart);
00085 int xRealWidth = Floor2Int(xPixelStart + .5f + xPixelCount + filter->xWidth) - Floor2Int(xPixelStart + .5f - filter->xWidth);
00086 int yRealHeight = Floor2Int(yPixelStart + .5f + yPixelCount + filter->yWidth) - Floor2Int(yPixelStart + .5f - filter->yWidth);
00087 samplePerPass = xRealWidth * yRealHeight;
00088
00089
00090 clampMethod = cM;
00091 write_EXR = cw_EXR;
00092 write_EXR_halftype = cw_EXR_halftype;
00093 write_EXR_applyimaging = cw_EXR_applyimaging;
00094 write_EXR_gamutclamp = cw_EXR_gamutclamp;
00095 write_EXR_ZBuf = cw_EXR_ZBuf;
00096 write_PNG = cw_PNG;
00097 write_PNG_16bit = cw_PNG_16bit;
00098 write_PNG_gamutclamp = cw_PNG_gamutclamp;
00099 write_PNG_ZBuf = cw_PNG_ZBuf;
00100 write_TGA = cw_TGA;
00101 write_TGA_gamutclamp = cw_TGA_gamutclamp;
00102 write_TGA_ZBuf = cw_TGA_ZBuf;
00103 write_EXR_channels = cw_EXR_channels;
00104 write_EXR_compressiontype = cw_EXR_compressiontype;
00105 write_EXR_ZBuf_normalizationtype = cw_EXR_ZBuf_normalizationtype;
00106 write_PNG_ZBuf_normalizationtype = cw_PNG_ZBuf_normalizationtype;
00107 write_PNG_channels = cw_PNG_channels;
00108 write_TGA_channels = cw_TGA_channels;
00109 write_TGA_ZBuf_normalizationtype = cw_TGA_ZBuf_normalizationtype;
00110
00111
00112 if(write_EXR_ZBuf || write_PNG_ZBuf || write_TGA_ZBuf)
00113 use_Zbuf = true;
00114 else
00115 use_Zbuf = false;
00116
00117
00118 m_TonemapKernel = d_TonemapKernel = p_TonemapKernel;
00119
00120 m_ReinhardPreScale = d_ReinhardPreScale = p_ReinhardPreScale;
00121 m_ReinhardPostScale = d_ReinhardPostScale = p_ReinhardPostScale;
00122 m_ReinhardBurn = d_ReinhardBurn = p_ReinhardBurn;
00123
00124 m_LinearSensitivity = d_LinearSensitivity = p_LinearSensitivity;
00125 m_LinearExposure = d_LinearExposure = p_LinearExposure;
00126 m_LinearFStop = d_LinearFStop = p_LinearFStop;
00127 m_LinearGamma = d_LinearGamma = p_LinearGamma;
00128
00129 m_ContrastYwa = d_ContrastYwa = p_ContrastYwa;
00130
00131 m_RGB_X_White = d_RGB_X_White = whitepoint[0];
00132 m_RGB_Y_White = d_RGB_Y_White = whitepoint[1];
00133 m_RGB_X_Red = d_RGB_X_Red = cs_red[0];
00134 m_RGB_Y_Red = d_RGB_Y_Red = cs_red[1];
00135 m_RGB_X_Green = d_RGB_X_Green = cs_green[0];
00136 m_RGB_Y_Green = d_RGB_Y_Green = cs_green[1];
00137 m_RGB_X_Blue = d_RGB_X_Blue = cs_blue[0];
00138 m_RGB_Y_Blue = d_RGB_Y_Blue = cs_blue[1];
00139 m_Gamma = d_Gamma = p_Gamma;
00140
00141 m_BloomUpdateLayer = false;
00142 m_BloomDeleteLayer = false;
00143 m_HaveBloomImage = false;
00144 m_BloomRadius = d_BloomRadius = 0.07f;
00145 m_BloomWeight = d_BloomWeight = 0.25f;
00146
00147 m_VignettingEnabled = d_VignettingEnabled = false;
00148 m_VignettingScale = d_VignettingScale = 0.4f;
00149
00150 m_AberrationEnabled = d_AberrationEnabled = false;
00151 m_AberrationAmount = d_AberrationAmount = 0.005f;
00152
00153 m_GlareUpdateLayer = false;
00154 m_GlareDeleteLayer = false;
00155 m_HaveGlareImage = false;
00156 m_glareImage = NULL;
00157 m_bloomImage = NULL;
00158 m_GlareAmount = d_GlareAmount = 0.03f;
00159 m_GlareRadius = d_GlareRadius = 0.03f;
00160 m_GlareBlades = d_GlareBlades = 3;
00161
00162 m_HistogramEnabled = d_HistogramEnabled = false;
00163
00164 m_GREYCStorationParams.Reset();
00165 d_GREYCStorationParams.Reset();
00166
00167 m_chiuParams.Reset();
00168 d_chiuParams.Reset();
00169
00170
00171 boost::xtime_get(&lastWriteImageTime, boost::TIME_UTC);
00172
00173
00174 reject_warmup_samples = ((double)xRealWidth * (double)yRealHeight) * reject_warmup;
00175
00176
00177 #define FILTER_TABLE_SIZE 16
00178 filterTable = new float[FILTER_TABLE_SIZE * FILTER_TABLE_SIZE];
00179 float *ftp = filterTable;
00180 for (int y = 0; y < FILTER_TABLE_SIZE; ++y) {
00181 float fy = ((float)y + .5f) * filter->yWidth / FILTER_TABLE_SIZE;
00182 for (int x = 0; x < FILTER_TABLE_SIZE; ++x) {
00183 float fx = ((float)x + .5f) * filter->xWidth / FILTER_TABLE_SIZE;
00184 *ftp++ = filter->Evaluate(fx, fy);
00185 }
00186 }
00187
00188 maxY = debug_mode ? INFINITY : 0.f;
00189 warmupSamples = 0;
00190 warmupComplete = debug_mode;
00191 }
00192
00193
00194 void FlexImageFilm::SetParameterValue(luxComponentParameters param, double value, int index)
00195 {
00196 switch (param) {
00197 case LUX_FILM_TM_TONEMAPKERNEL:
00198 m_TonemapKernel = Floor2Int(value);
00199 break;
00200
00201 case LUX_FILM_TM_REINHARD_PRESCALE:
00202 m_ReinhardPreScale = value;
00203 break;
00204 case LUX_FILM_TM_REINHARD_POSTSCALE:
00205 m_ReinhardPostScale = value;
00206 break;
00207 case LUX_FILM_TM_REINHARD_BURN:
00208 m_ReinhardBurn = value;
00209 break;
00210
00211 case LUX_FILM_TM_LINEAR_SENSITIVITY:
00212 m_LinearSensitivity = value;
00213 break;
00214 case LUX_FILM_TM_LINEAR_EXPOSURE:
00215 m_LinearExposure = value;
00216 break;
00217 case LUX_FILM_TM_LINEAR_FSTOP:
00218 m_LinearFStop = value;
00219 break;
00220 case LUX_FILM_TM_LINEAR_GAMMA:
00221 m_LinearGamma = value;
00222 break;
00223
00224 case LUX_FILM_TM_CONTRAST_YWA:
00225 m_ContrastYwa = value;
00226 break;
00227
00228 case LUX_FILM_TORGB_X_WHITE:
00229 m_RGB_X_White = value;
00230 break;
00231 case LUX_FILM_TORGB_Y_WHITE:
00232 m_RGB_Y_White = value;
00233 break;
00234 case LUX_FILM_TORGB_X_RED:
00235 m_RGB_X_Red = value;
00236 break;
00237 case LUX_FILM_TORGB_Y_RED:
00238 m_RGB_Y_Red = value;
00239 break;
00240 case LUX_FILM_TORGB_X_GREEN:
00241 m_RGB_X_Green = value;
00242 break;
00243 case LUX_FILM_TORGB_Y_GREEN:
00244 m_RGB_Y_Green = value;
00245 break;
00246 case LUX_FILM_TORGB_X_BLUE:
00247 m_RGB_X_Blue = value;
00248 break;
00249 case LUX_FILM_TORGB_Y_BLUE:
00250 m_RGB_Y_Blue = value;
00251 break;
00252 case LUX_FILM_TORGB_GAMMA:
00253 m_Gamma = value;
00254 break;
00255 case LUX_FILM_UPDATEBLOOMLAYER:
00256 m_BloomUpdateLayer = (value != 0.f);
00257 break;
00258 case LUX_FILM_DELETEBLOOMLAYER:
00259 m_BloomDeleteLayer = (value != 0.f);
00260 break;
00261
00262 case LUX_FILM_BLOOMRADIUS:
00263 m_BloomRadius = value;
00264 break;
00265 case LUX_FILM_BLOOMWEIGHT:
00266 m_BloomWeight = value;
00267 break;
00268
00269 case LUX_FILM_VIGNETTING_ENABLED:
00270 m_VignettingEnabled = (value != 0.f);
00271 break;
00272 case LUX_FILM_VIGNETTING_SCALE:
00273 m_VignettingScale = value;
00274 break;
00275
00276 case LUX_FILM_ABERRATION_ENABLED:
00277 m_AberrationEnabled = (value != 0.f);
00278 break;
00279 case LUX_FILM_ABERRATION_AMOUNT:
00280 m_AberrationAmount = value;
00281 break;
00282
00283 case LUX_FILM_UPDATEGLARELAYER:
00284 m_GlareUpdateLayer = (value != 0.f);
00285 break;
00286 case LUX_FILM_DELETEGLARELAYER:
00287 m_GlareDeleteLayer = (value != 0.f);
00288 break;
00289 case LUX_FILM_GLARE_AMOUNT:
00290 m_GlareAmount = value;
00291 break;
00292 case LUX_FILM_GLARE_RADIUS:
00293 m_GlareRadius = value;
00294 break;
00295 case LUX_FILM_GLARE_BLADES:
00296 m_GlareBlades = (int)value;
00297 break;
00298
00299 case LUX_FILM_HISTOGRAM_ENABLED:
00300 m_HistogramEnabled = (value != 0.f);
00301 break;
00302
00303 case LUX_FILM_NOISE_CHIU_ENABLED:
00304 m_chiuParams.enabled = (value != 0.f);
00305 break;
00306 case LUX_FILM_NOISE_CHIU_RADIUS:
00307 m_chiuParams.radius = value;
00308 break;
00309 case LUX_FILM_NOISE_CHIU_INCLUDECENTER:
00310 m_chiuParams.includecenter = (value != 0.f);
00311 break;
00312
00313 case LUX_FILM_NOISE_GREYC_ENABLED:
00314 m_GREYCStorationParams.enabled = (value != 0.f);
00315 break;
00316 case LUX_FILM_NOISE_GREYC_AMPLITUDE:
00317 m_GREYCStorationParams.amplitude = value;
00318 break;
00319 case LUX_FILM_NOISE_GREYC_NBITER:
00320 m_GREYCStorationParams.nb_iter = int(value);
00321 break;
00322 case LUX_FILM_NOISE_GREYC_SHARPNESS:
00323 m_GREYCStorationParams.sharpness = value;
00324 break;
00325 case LUX_FILM_NOISE_GREYC_ANISOTROPY:
00326 m_GREYCStorationParams.anisotropy = value;
00327 break;
00328 case LUX_FILM_NOISE_GREYC_ALPHA:
00329 m_GREYCStorationParams.alpha = value;
00330 break;
00331 case LUX_FILM_NOISE_GREYC_SIGMA:
00332 m_GREYCStorationParams.sigma = value;
00333 break;
00334 case LUX_FILM_NOISE_GREYC_FASTAPPROX:
00335 m_GREYCStorationParams.fast_approx = (value != 0.f);
00336 break;
00337 case LUX_FILM_NOISE_GREYC_GAUSSPREC:
00338 m_GREYCStorationParams.gauss_prec = value;
00339 break;
00340 case LUX_FILM_NOISE_GREYC_DL:
00341 m_GREYCStorationParams.dl = value;
00342 break;
00343 case LUX_FILM_NOISE_GREYC_DA:
00344 m_GREYCStorationParams.da = value;
00345 break;
00346 case LUX_FILM_NOISE_GREYC_INTERP:
00347 m_GREYCStorationParams.interp = (int) value;
00348 break;
00349 case LUX_FILM_NOISE_GREYC_TILE:
00350 m_GREYCStorationParams.tile = (int) value;
00351 break;
00352 case LUX_FILM_NOISE_GREYC_BTILE:
00353 m_GREYCStorationParams.btile = (int) value;
00354 break;
00355 case LUX_FILM_NOISE_GREYC_THREADS:
00356 m_GREYCStorationParams.threads = (int) value;
00357 break;
00358
00359 case LUX_FILM_LG_SCALE:
00360 SetGroupScale(index, value);
00361 break;
00362 case LUX_FILM_LG_ENABLE:
00363 SetGroupEnable(index, value != 0.f);
00364 break;
00365 case LUX_FILM_LG_SCALE_RED: {
00366 RGBColor color(GetGroupRGBScale(index));
00367 color.c[0] = value;
00368 SetGroupRGBScale(index, color);
00369 break;
00370 }
00371 case LUX_FILM_LG_SCALE_GREEN: {
00372 RGBColor color(GetGroupRGBScale(index));
00373 color.c[1] = value;
00374 SetGroupRGBScale(index, color);
00375 break;
00376 }
00377 case LUX_FILM_LG_SCALE_BLUE: {
00378 RGBColor color(GetGroupRGBScale(index));
00379 color.c[2] = value;
00380 SetGroupRGBScale(index, color);
00381 break;
00382 }
00383 case LUX_FILM_LG_TEMPERATURE: {
00384 SetGroupTemperature(index, value);
00385 break;
00386 }
00387
00388 default:
00389 break;
00390 }
00391 }
00392 double FlexImageFilm::GetParameterValue(luxComponentParameters param, int index)
00393 {
00394 switch (param) {
00395 case LUX_FILM_TM_TONEMAPKERNEL:
00396 return m_TonemapKernel;
00397 break;
00398
00399 case LUX_FILM_TM_REINHARD_PRESCALE:
00400 return m_ReinhardPreScale;
00401 break;
00402 case LUX_FILM_TM_REINHARD_POSTSCALE:
00403 return m_ReinhardPostScale;
00404 break;
00405 case LUX_FILM_TM_REINHARD_BURN:
00406 return m_ReinhardBurn;
00407 break;
00408
00409 case LUX_FILM_TM_LINEAR_SENSITIVITY:
00410 return m_LinearSensitivity;
00411 break;
00412 case LUX_FILM_TM_LINEAR_EXPOSURE:
00413 return m_LinearExposure;
00414 break;
00415 case LUX_FILM_TM_LINEAR_FSTOP:
00416 return m_LinearFStop;
00417 break;
00418 case LUX_FILM_TM_LINEAR_GAMMA:
00419 return m_LinearGamma;
00420 break;
00421
00422 case LUX_FILM_TM_CONTRAST_YWA:
00423 return m_ContrastYwa;
00424 break;
00425
00426 case LUX_FILM_TORGB_X_WHITE:
00427 return m_RGB_X_White;
00428 break;
00429 case LUX_FILM_TORGB_Y_WHITE:
00430 return m_RGB_Y_White;
00431 break;
00432 case LUX_FILM_TORGB_X_RED:
00433 return m_RGB_X_Red;
00434 break;
00435 case LUX_FILM_TORGB_Y_RED:
00436 return m_RGB_Y_Red;
00437 break;
00438 case LUX_FILM_TORGB_X_GREEN:
00439 return m_RGB_X_Green;
00440 break;
00441 case LUX_FILM_TORGB_Y_GREEN:
00442 return m_RGB_Y_Green;
00443 break;
00444 case LUX_FILM_TORGB_X_BLUE:
00445 return m_RGB_X_Blue;
00446 break;
00447 case LUX_FILM_TORGB_Y_BLUE:
00448 return m_RGB_Y_Blue;
00449 break;
00450 case LUX_FILM_TORGB_GAMMA:
00451 return m_Gamma;
00452 break;
00453
00454 case LUX_FILM_BLOOMRADIUS:
00455 return m_BloomRadius;
00456 break;
00457 case LUX_FILM_BLOOMWEIGHT:
00458 return m_BloomWeight;
00459 break;
00460
00461 case LUX_FILM_VIGNETTING_ENABLED:
00462 return m_VignettingEnabled;
00463 break;
00464 case LUX_FILM_VIGNETTING_SCALE:
00465 return m_VignettingScale;
00466 break;
00467
00468 case LUX_FILM_ABERRATION_ENABLED:
00469 return m_AberrationEnabled;
00470 break;
00471 case LUX_FILM_ABERRATION_AMOUNT:
00472 return m_AberrationAmount;
00473 break;
00474
00475 case LUX_FILM_GLARE_AMOUNT:
00476 return m_GlareAmount;
00477 break;
00478 case LUX_FILM_GLARE_RADIUS:
00479 return m_GlareRadius;
00480 break;
00481 case LUX_FILM_GLARE_BLADES:
00482 return m_GlareBlades;
00483 break;
00484
00485 case LUX_FILM_HISTOGRAM_ENABLED:
00486 return m_HistogramEnabled;
00487 break;
00488
00489 case LUX_FILM_NOISE_CHIU_ENABLED:
00490 return m_chiuParams.enabled;
00491 break;
00492 case LUX_FILM_NOISE_CHIU_RADIUS:
00493 return m_chiuParams.radius;
00494 break;
00495 case LUX_FILM_NOISE_CHIU_INCLUDECENTER:
00496 return m_chiuParams.includecenter;
00497 break;
00498
00499 case LUX_FILM_NOISE_GREYC_ENABLED:
00500 return m_GREYCStorationParams.enabled;
00501 break;
00502 case LUX_FILM_NOISE_GREYC_AMPLITUDE:
00503 return m_GREYCStorationParams.amplitude;
00504 break;
00505 case LUX_FILM_NOISE_GREYC_NBITER:
00506 return m_GREYCStorationParams.nb_iter;
00507 break;
00508 case LUX_FILM_NOISE_GREYC_SHARPNESS:
00509 return m_GREYCStorationParams.sharpness;
00510 break;
00511 case LUX_FILM_NOISE_GREYC_ANISOTROPY:
00512 return m_GREYCStorationParams.anisotropy;
00513 break;
00514 case LUX_FILM_NOISE_GREYC_ALPHA:
00515 return m_GREYCStorationParams.alpha;
00516 break;
00517 case LUX_FILM_NOISE_GREYC_SIGMA:
00518 return m_GREYCStorationParams.sigma;
00519 break;
00520 case LUX_FILM_NOISE_GREYC_FASTAPPROX:
00521 return m_GREYCStorationParams.fast_approx;
00522 break;
00523 case LUX_FILM_NOISE_GREYC_GAUSSPREC:
00524 return m_GREYCStorationParams.gauss_prec;
00525 break;
00526 case LUX_FILM_NOISE_GREYC_DL:
00527 return m_GREYCStorationParams.dl;
00528 break;
00529 case LUX_FILM_NOISE_GREYC_DA:
00530 return m_GREYCStorationParams.da;
00531 break;
00532 case LUX_FILM_NOISE_GREYC_INTERP:
00533 return m_GREYCStorationParams.interp;
00534 break;
00535 case LUX_FILM_NOISE_GREYC_TILE:
00536 return m_GREYCStorationParams.tile;
00537 break;
00538 case LUX_FILM_NOISE_GREYC_BTILE:
00539 return m_GREYCStorationParams.btile;
00540 break;
00541 case LUX_FILM_NOISE_GREYC_THREADS:
00542 return m_GREYCStorationParams.threads;
00543 break;
00544
00545 case LUX_FILM_LG_COUNT:
00546 return GetNumBufferGroups();
00547 break;
00548 case LUX_FILM_LG_ENABLE:
00549 return GetGroupEnable(index);
00550 break;
00551 case LUX_FILM_LG_SCALE:
00552 return GetGroupScale(index);
00553 break;
00554 case LUX_FILM_LG_SCALE_RED:
00555 return GetGroupRGBScale(index).c[0];
00556 break;
00557 case LUX_FILM_LG_SCALE_GREEN:
00558 return GetGroupRGBScale(index).c[1];
00559 break;
00560 case LUX_FILM_LG_SCALE_BLUE:
00561 return GetGroupRGBScale(index).c[2];
00562 break;
00563 case LUX_FILM_LG_TEMPERATURE:
00564 return GetGroupTemperature(index);
00565 break;
00566
00567 default:
00568 break;
00569 }
00570 return 0.;
00571 }
00572 double FlexImageFilm::GetDefaultParameterValue(luxComponentParameters param, int index)
00573 {
00574 switch (param) {
00575 case LUX_FILM_TM_TONEMAPKERNEL:
00576 return d_TonemapKernel;
00577 break;
00578
00579 case LUX_FILM_TM_REINHARD_PRESCALE:
00580 return d_ReinhardPreScale;
00581 break;
00582 case LUX_FILM_TM_REINHARD_POSTSCALE:
00583 return d_ReinhardPostScale;
00584 break;
00585 case LUX_FILM_TM_REINHARD_BURN:
00586 return d_ReinhardBurn;
00587 break;
00588
00589 case LUX_FILM_TM_LINEAR_SENSITIVITY:
00590 return d_LinearSensitivity;
00591 break;
00592 case LUX_FILM_TM_LINEAR_EXPOSURE:
00593 return d_LinearExposure;
00594 break;
00595 case LUX_FILM_TM_LINEAR_FSTOP:
00596 return d_LinearFStop;
00597 break;
00598 case LUX_FILM_TM_LINEAR_GAMMA:
00599 return d_LinearGamma;
00600 break;
00601
00602 case LUX_FILM_TM_CONTRAST_YWA:
00603 return d_ContrastYwa;
00604 break;
00605
00606 case LUX_FILM_TORGB_X_WHITE:
00607 return d_RGB_X_White;
00608 break;
00609 case LUX_FILM_TORGB_Y_WHITE:
00610 return d_RGB_Y_White;
00611 break;
00612 case LUX_FILM_TORGB_X_RED:
00613 return d_RGB_X_Red;
00614 break;
00615 case LUX_FILM_TORGB_Y_RED:
00616 return d_RGB_Y_Red;
00617 break;
00618 case LUX_FILM_TORGB_X_GREEN:
00619 return d_RGB_X_Green;
00620 break;
00621 case LUX_FILM_TORGB_Y_GREEN:
00622 return d_RGB_Y_Green;
00623 break;
00624 case LUX_FILM_TORGB_X_BLUE:
00625 return d_RGB_X_Blue;
00626 break;
00627 case LUX_FILM_TORGB_Y_BLUE:
00628 return d_RGB_Y_Blue;
00629 break;
00630 case LUX_FILM_TORGB_GAMMA:
00631 return d_Gamma;
00632 break;
00633
00634 case LUX_FILM_BLOOMRADIUS:
00635 return d_BloomRadius;
00636 break;
00637 case LUX_FILM_BLOOMWEIGHT:
00638 return d_BloomWeight;
00639 break;
00640
00641 case LUX_FILM_VIGNETTING_ENABLED:
00642 return d_VignettingEnabled;
00643 break;
00644 case LUX_FILM_VIGNETTING_SCALE:
00645 return d_VignettingScale;
00646 break;
00647
00648 case LUX_FILM_ABERRATION_ENABLED:
00649 return d_AberrationEnabled;
00650 break;
00651 case LUX_FILM_ABERRATION_AMOUNT:
00652 return d_AberrationAmount;
00653 break;
00654
00655 case LUX_FILM_GLARE_AMOUNT:
00656 return d_GlareAmount;
00657 break;
00658 case LUX_FILM_GLARE_RADIUS:
00659 return d_GlareRadius;
00660 break;
00661 case LUX_FILM_GLARE_BLADES:
00662 return d_GlareBlades;
00663 break;
00664
00665 case LUX_FILM_HISTOGRAM_ENABLED:
00666 return d_HistogramEnabled;
00667 break;
00668
00669 case LUX_FILM_NOISE_CHIU_ENABLED:
00670 return d_chiuParams.enabled;
00671 break;
00672 case LUX_FILM_NOISE_CHIU_RADIUS:
00673 return d_chiuParams.radius;
00674 break;
00675 case LUX_FILM_NOISE_CHIU_INCLUDECENTER:
00676 return d_chiuParams.includecenter;
00677 break;
00678
00679 case LUX_FILM_NOISE_GREYC_ENABLED:
00680 return d_GREYCStorationParams.enabled;
00681 break;
00682 case LUX_FILM_NOISE_GREYC_AMPLITUDE:
00683 return d_GREYCStorationParams.amplitude;
00684 break;
00685 case LUX_FILM_NOISE_GREYC_NBITER:
00686 return d_GREYCStorationParams.nb_iter;
00687 break;
00688 case LUX_FILM_NOISE_GREYC_SHARPNESS:
00689 return d_GREYCStorationParams.sharpness;
00690 break;
00691 case LUX_FILM_NOISE_GREYC_ANISOTROPY:
00692 return d_GREYCStorationParams.anisotropy;
00693 break;
00694 case LUX_FILM_NOISE_GREYC_ALPHA:
00695 return d_GREYCStorationParams.alpha;
00696 break;
00697 case LUX_FILM_NOISE_GREYC_SIGMA:
00698 return d_GREYCStorationParams.sigma;
00699 break;
00700 case LUX_FILM_NOISE_GREYC_FASTAPPROX:
00701 return d_GREYCStorationParams.fast_approx;
00702 break;
00703 case LUX_FILM_NOISE_GREYC_GAUSSPREC:
00704 return d_GREYCStorationParams.gauss_prec;
00705 break;
00706 case LUX_FILM_NOISE_GREYC_DL:
00707 return d_GREYCStorationParams.dl;
00708 break;
00709 case LUX_FILM_NOISE_GREYC_DA:
00710 return d_GREYCStorationParams.da;
00711 break;
00712 case LUX_FILM_NOISE_GREYC_INTERP:
00713 return d_GREYCStorationParams.interp;
00714 break;
00715 case LUX_FILM_NOISE_GREYC_TILE:
00716 return d_GREYCStorationParams.tile;
00717 break;
00718 case LUX_FILM_NOISE_GREYC_BTILE:
00719 return d_GREYCStorationParams.btile;
00720 break;
00721 case LUX_FILM_NOISE_GREYC_THREADS:
00722 return d_GREYCStorationParams.threads;
00723 break;
00724
00725 case LUX_FILM_LG_ENABLE:
00726 return true;
00727 break;
00728 case LUX_FILM_LG_SCALE:
00729 return 1.f;
00730 break;
00731 case LUX_FILM_LG_SCALE_RED:
00732 return 1.f;
00733 break;
00734 case LUX_FILM_LG_SCALE_GREEN:
00735 return 1.f;
00736 break;
00737 case LUX_FILM_LG_SCALE_BLUE:
00738 return 1.f;
00739 break;
00740 case LUX_FILM_LG_TEMPERATURE:
00741 return 0.f;
00742 break;
00743
00744 default:
00745 break;
00746 }
00747 return 0.;
00748 }
00749
00750 void FlexImageFilm::SetStringParameterValue(luxComponentParameters param, const string& value, int index) {
00751 switch(param) {
00752 case LUX_FILM_LG_NAME:
00753 return SetGroupName(index, value);
00754 default:
00755 break;
00756 }
00757 }
00758 string FlexImageFilm::GetStringParameterValue(luxComponentParameters param, int index) {
00759 switch(param) {
00760 case LUX_FILM_LG_NAME:
00761 return GetGroupName(index);
00762 default:
00763 break;
00764 }
00765 return "";
00766 }
00767
00768 void FlexImageFilm::GetSampleExtent(int *xstart, int *xend,
00769 int *ystart, int *yend) const
00770 {
00771 *xstart = Floor2Int(xPixelStart + .5f - filter->xWidth);
00772 *xend = Floor2Int(xPixelStart + .5f + xPixelCount + filter->xWidth);
00773 *ystart = Floor2Int(yPixelStart + .5f - filter->yWidth);
00774 *yend = Floor2Int(yPixelStart + .5f + yPixelCount + filter->yWidth);
00775 }
00776
00777 void FlexImageFilm::RequestBufferGroups(const vector<string> &bg)
00778 {
00779 for (u_int i = 0; i < bg.size(); ++i)
00780 bufferGroups.push_back(BufferGroup(bg[i]));
00781 }
00782
00783 int FlexImageFilm::RequestBuffer(BufferType type, BufferOutputConfig output,
00784 const string& filePostfix)
00785 {
00786 bufferConfigs.push_back(BufferConfig(type, output, filePostfix));
00787 return bufferConfigs.size() - 1;
00788 }
00789
00790 void FlexImageFilm::CreateBuffers()
00791 {
00792 if (bufferGroups.size() == 0)
00793 bufferGroups.push_back(BufferGroup("default"));
00794 for (u_int i = 0; i < bufferGroups.size(); ++i)
00795 bufferGroups[i].CreateBuffers(bufferConfigs,xPixelCount,yPixelCount);
00796
00797
00798 if(use_Zbuf)
00799 ZBuffer = new PerPixelNormalizedFloatBuffer(xPixelCount,yPixelCount);
00800
00801
00802 if(writeResumeFlm && !restartResumeFlm) {
00803
00804 string fname = filename+".flm";
00805 std::ifstream ifs(fname.c_str(), std::ios_base::in | std::ios_base::binary);
00806
00807 if(ifs.good()) {
00808
00809 luxError(LUX_NOERROR, LUX_INFO, (std::string("Reading film status from file ")+fname).c_str());
00810 UpdateFilm(ifs);
00811 }
00812
00813 ifs.close();
00814 }
00815 }
00816
00817 void FlexImageFilm::SetGroupName(u_int index, const string& name)
00818 {
00819 if( index >= bufferGroups.size())
00820 return;
00821 bufferGroups[index].name = name;
00822 }
00823 string FlexImageFilm::GetGroupName(u_int index) const
00824 {
00825 if (index >= bufferGroups.size())
00826 return "";
00827 return bufferGroups[index].name;
00828 }
00829 void FlexImageFilm::SetGroupEnable(u_int index, bool status)
00830 {
00831 if (index >= bufferGroups.size())
00832 return;
00833 bufferGroups[index].enable = status;
00834 }
00835 bool FlexImageFilm::GetGroupEnable(u_int index) const
00836 {
00837 if (index >= bufferGroups.size())
00838 return false;
00839 return bufferGroups[index].enable;
00840 }
00841 void FlexImageFilm::SetGroupScale(u_int index, float value)
00842 {
00843 if (index >= bufferGroups.size())
00844 return;
00845 bufferGroups[index].globalScale = value;
00846 ComputeGroupScale(index);
00847 }
00848 float FlexImageFilm::GetGroupScale(u_int index) const
00849 {
00850 if (index >= bufferGroups.size())
00851 return 0.f;
00852 return bufferGroups[index].globalScale;
00853 }
00854 void FlexImageFilm::SetGroupRGBScale(u_int index, const RGBColor &value)
00855 {
00856 if (index >= bufferGroups.size())
00857 return;
00858 bufferGroups[index].rgbScale = value;
00859 ComputeGroupScale(index);
00860 }
00861 RGBColor FlexImageFilm::GetGroupRGBScale(u_int index) const
00862 {
00863 if (index >= bufferGroups.size())
00864 return 0.f;
00865 return bufferGroups[index].rgbScale;
00866 }
00867 void FlexImageFilm::SetGroupTemperature(u_int index, float value)
00868 {
00869 if (index >= bufferGroups.size())
00870 return;
00871 bufferGroups[index].temperature = value;
00872 ComputeGroupScale(index);
00873 }
00874 float FlexImageFilm::GetGroupTemperature(u_int index) const
00875 {
00876 if (index >= bufferGroups.size())
00877 return 0.f;
00878 return bufferGroups[index].temperature;
00879 }
00880 void FlexImageFilm::ComputeGroupScale(u_int index)
00881 {
00882 const XYZColor white(colorSpace.ToXYZ(RGBColor(1.f)));
00883 bufferGroups[index].scale =
00884 colorSpace.ToXYZ(bufferGroups[index].rgbScale) / white;
00885 if (bufferGroups[index].temperature > 0.f) {
00886 XYZColor factor(BlackbodySPD(bufferGroups[index].temperature).ToXYZ());
00887 bufferGroups[index].scale *= factor / (factor.Y() * white);
00888 }
00889 bufferGroups[index].scale *= bufferGroups[index].globalScale;
00890 }
00891
00892 void FlexImageFilm::AddSampleCount(float count) {
00893 if (haltTime > 0) {
00894
00895 boost::xtime t;
00896 boost::xtime_get(&t, boost::TIME_UTC);
00897 if (t.sec - creationTime.sec > haltTime)
00898 enoughSamplePerPixel = true;
00899 }
00900
00901 for (u_int i = 0; i < bufferGroups.size(); ++i) {
00902 bufferGroups[i].numberOfSamples += count;
00903
00904
00905
00906
00907
00908 if ((haltSamplePerPixel > 0) &&
00909 (bufferGroups[i].numberOfSamples >= haltSamplePerPixel * samplePerPass))
00910 enoughSamplePerPixel = true;
00911 }
00912 }
00913
00914 void FlexImageFilm::AddSample(Contribution *contrib) {
00915 XYZColor xyz = contrib->color;
00916 const float alpha = contrib->alpha;
00917 const float weight = contrib->variance;
00918
00919
00920 if (xyz.IsNaN() || xyz.Y() < -1e-5f || isinf(xyz.Y())) {
00921 if(debug_mode) {
00922 std::stringstream ss;
00923 ss << "Out of bound intensity in FlexImageFilm::AddSample: "
00924 << xyz.Y() << ", sample discarded";
00925 luxError(LUX_LIMIT, LUX_WARNING, ss.str().c_str());
00926 }
00927 return;
00928 }
00929
00930 if (alpha < 0 || isnan(alpha) || isinf(alpha))
00931 return;
00932
00933 if (weight < 0 || isnan(weight) || isinf(weight))
00934 return;
00935
00936
00937 if (warmupComplete && xyz.Y() > maxY)
00938 return;
00939 else {
00940 maxY = max(maxY, xyz.Y());
00941 ++warmupSamples;
00942 if (warmupSamples >= reject_warmup_samples)
00943 warmupComplete = true;
00944 }
00945
00946 if (premultiplyAlpha)
00947 xyz *= alpha;
00948
00949 BufferGroup ¤tGroup = bufferGroups[contrib->bufferGroup];
00950 Buffer *buffer = currentGroup.getBuffer(contrib->buffer);
00951
00952
00953 float dImageX = contrib->imageX - 0.5f;
00954 float dImageY = contrib->imageY - 0.5f;
00955 int x0 = Ceil2Int (dImageX - filter->xWidth);
00956 int x1 = Floor2Int(dImageX + filter->xWidth);
00957 int y0 = Ceil2Int (dImageY - filter->yWidth);
00958 int y1 = Floor2Int(dImageY + filter->yWidth);
00959
00960
00961
00962
00963 if (x1 < x0 || y1 < y0) return;
00964
00965
00966
00967 int ifx[32];
00968 for (int x = x0; x <= x1; ++x) {
00969 float fx = fabsf((x - dImageX) *
00970 filter->invXWidth * FILTER_TABLE_SIZE);
00971 ifx[x-x0] = min(Floor2Int(fx), FILTER_TABLE_SIZE-1);
00972 }
00973
00974 int ify[32];
00975 for (int y = y0; y <= y1; ++y) {
00976 float fy = fabsf((y - dImageY) *
00977 filter->invYWidth * FILTER_TABLE_SIZE);
00978 ify[y-y0] = min(Floor2Int(fy), FILTER_TABLE_SIZE-1);
00979 }
00980 float filterNorm = 0.f;
00981 for (int y = y0; y <= y1; ++y) {
00982 for (int x = x0; x <= x1; ++x) {
00983 const int offset = ify[y-y0]*FILTER_TABLE_SIZE + ifx[x-x0];
00984 filterNorm += filterTable[offset];
00985 }
00986 }
00987 filterNorm = weight / filterNorm;
00988
00989 for (int y = max(y0, yPixelStart); y <= min(y1, yPixelStart + yPixelCount - 1); ++y) {
00990 for (int x = max(x0, xPixelStart); x <= min(x1, xPixelStart + xPixelCount - 1); ++x) {
00991
00992 const int offset = ify[y-y0]*FILTER_TABLE_SIZE + ifx[x-x0];
00993 const float filterWt = filterTable[offset] * filterNorm;
00994
00995 buffer->Add(x - xPixelStart,y - yPixelStart,
00996 xyz, alpha, filterWt);
00997
00998 if(use_Zbuf && contrib->zdepth != 0.f)
00999 ZBuffer->Add(x - xPixelStart, y - yPixelStart, contrib->zdepth, 1.0f);
01000 }
01001 }
01002
01003 CheckWriteOuputInterval();
01004 }
01005
01006 void FlexImageFilm::CheckWriteOuputInterval()
01007 {
01008
01009 boost::xtime currentTime;
01010 boost::xtime_get(¤tTime, boost::TIME_UTC);
01011 bool timeToWriteImage = (currentTime.sec - lastWriteImageTime.sec > writeInterval);
01012
01013
01014 if (timeToWriteImage) {
01015 WriteImage(IMAGE_FILEOUTPUT);
01016
01017
01018
01019 boost::xtime_get(&lastWriteImageTime, boost::TIME_UTC);
01020 }
01021 }
01022
01023 void FlexImageFilm::WriteImage2(ImageType type, vector<XYZColor> &xyzcolor, vector<float> &alpha, string postfix)
01024 {
01025
01026 colorSpace = ColorSystem(m_RGB_X_Red, m_RGB_Y_Red,
01027 m_RGB_X_Green, m_RGB_Y_Green,
01028 m_RGB_X_Blue, m_RGB_Y_Blue,
01029 m_RGB_X_White, m_RGB_Y_White, 1.f);
01030
01031
01032 vector<float> zBuf;
01033 if(use_Zbuf && (write_EXR_ZBuf || write_PNG_ZBuf || write_TGA_ZBuf)) {
01034 const u_int nPix = xPixelCount * yPixelCount;
01035 zBuf.resize(nPix, 0.f);
01036 for (int offset = 0, y = 0; y < yPixelCount; ++y) {
01037 for (int x = 0; x < xPixelCount; ++x,++offset) {
01038 zBuf[offset] = ZBuffer->GetData(x, y);
01039 }
01040 }
01041 }
01042
01043 if (type & IMAGE_FILEOUTPUT) {
01044
01045 if (write_EXR && !write_EXR_applyimaging) {
01046
01047 const u_int nPix = xPixelCount * yPixelCount;
01048 vector<RGBColor> rgbColor(nPix);
01049 for ( u_int i = 0; i < nPix; i++ )
01050 rgbColor[i] = colorSpace.ToRGBConstrained(xyzcolor[i]);
01051
01052 WriteEXRImage(rgbColor, alpha, filename + postfix + ".exr", zBuf);
01053 }
01054
01055
01056 if (writeResumeFlm)
01057 WriteResumeFilm(filename + ".flm");
01058 }
01059
01060
01061 if (((type & IMAGE_FRAMEBUFFER) && framebuffer) ||
01062 ((type & IMAGE_FILEOUTPUT) && ((write_EXR && write_EXR_applyimaging) || write_TGA || write_PNG))) {
01063
01064 ParamSet toneParams;
01065 std::string tmkernel = "reinhard";
01066 if(m_TonemapKernel == 0) {
01067
01068 toneParams.AddFloat("prescale", &m_ReinhardPreScale, 1);
01069 toneParams.AddFloat("postscale", &m_ReinhardPostScale, 1);
01070 toneParams.AddFloat("burn", &m_ReinhardBurn, 1);
01071 tmkernel = "reinhard";
01072 } else if(m_TonemapKernel == 1) {
01073
01074 toneParams.AddFloat("sensitivity", &m_LinearSensitivity, 1);
01075 toneParams.AddFloat("exposure", &m_LinearExposure, 1);
01076 toneParams.AddFloat("fstop", &m_LinearFStop, 1);
01077 toneParams.AddFloat("gamma", &m_LinearGamma, 1);
01078 tmkernel = "linear";
01079 } else if(m_TonemapKernel == 2) {
01080
01081 toneParams.AddFloat("ywa", &m_ContrastYwa, 1);
01082 tmkernel = "contrast";
01083 } else {
01084
01085 tmkernel = "maxwhite";
01086 }
01087
01088
01089 if (!m_BloomUpdateLayer && m_BloomDeleteLayer && m_HaveBloomImage) {
01090
01091 m_HaveBloomImage = false;
01092 delete[] m_bloomImage;
01093 m_bloomImage = NULL;
01094 m_BloomDeleteLayer = false;
01095 }
01096
01097 if (!m_GlareUpdateLayer && m_GlareDeleteLayer && m_HaveGlareImage) {
01098
01099 m_HaveGlareImage = false;
01100 delete[] m_glareImage;
01101 m_glareImage = NULL;
01102 m_GlareDeleteLayer = false;
01103 }
01104
01105
01106 ApplyImagingPipeline(xyzcolor, xPixelCount, yPixelCount, m_GREYCStorationParams, m_chiuParams,
01107 colorSpace, histogram, m_HistogramEnabled, m_HaveBloomImage, m_bloomImage, m_BloomUpdateLayer,
01108 m_BloomRadius, m_BloomWeight, m_VignettingEnabled, m_VignettingScale, m_AberrationEnabled, m_AberrationAmount,
01109 m_HaveGlareImage, m_glareImage, m_GlareUpdateLayer, m_GlareAmount, m_GlareRadius, m_GlareBlades,
01110 tmkernel.c_str(), &toneParams, m_Gamma, 0.f);
01111
01112
01113 vector<RGBColor> &rgbcolor = reinterpret_cast<vector<RGBColor> &>(xyzcolor);
01114
01115
01116 m_BloomUpdateLayer = false;
01117 m_GlareUpdateLayer = false;
01118
01119 if (type & IMAGE_FILEOUTPUT) {
01120
01121 if ((write_EXR && write_EXR_applyimaging))
01122 WriteEXRImage(rgbcolor, alpha, filename + postfix + ".exr", zBuf);
01123 }
01124
01125
01126 if ((type & IMAGE_FILEOUTPUT) || (type & IMAGE_FRAMEBUFFER)) {
01127
01128 const u_int nPix = xPixelCount * yPixelCount;
01129 for (u_int i = 0; i < nPix; ++i)
01130 rgbcolor[i] = colorSpace.Limit(rgbcolor[i], clampMethod);
01131
01132
01133 if ((type & IMAGE_FILEOUTPUT) && write_TGA)
01134 WriteTGAImage(rgbcolor, alpha, filename + postfix + ".tga");
01135
01136 if ((type & IMAGE_FILEOUTPUT) && write_PNG)
01137 WritePNGImage(rgbcolor, alpha, filename + postfix + ".png");
01138
01139 if ((type & IMAGE_FRAMEBUFFER) && framebuffer) {
01140 for (u_int i = 0; i < nPix; i++) {
01141 framebuffer[3 * i] = static_cast<unsigned char>(Clamp(256 * rgbcolor[i].c[0], 0.f, 255.f));
01142 framebuffer[3 * i + 1] = static_cast<unsigned char>(Clamp(256 * rgbcolor[i].c[1], 0.f, 255.f));
01143 framebuffer[3 * i + 2] = static_cast<unsigned char>(Clamp(256 * rgbcolor[i].c[2], 0.f, 255.f));
01144 }
01145 }
01146 }
01147 }
01148 }
01149
01150 void FlexImageFilm::WriteImage(ImageType type)
01151 {
01152 const int nPix = xPixelCount * yPixelCount;
01153 vector<XYZColor> pixels(nPix);
01154 vector<float> alpha(nPix), alphaWeight(nPix, 0.f);
01155
01156
01157
01158
01159
01160 for(u_int j = 0; j < bufferGroups.size(); ++j) {
01161 if (!bufferGroups[j].enable)
01162 continue;
01163
01164 for(u_int i = 0; i < bufferConfigs.size(); ++i) {
01165 const Buffer &buffer = *(bufferGroups[j].buffers[i]);
01166
01167 if (!(bufferConfigs[i].output & BUF_STANDALONE))
01168 continue;
01169
01170 buffer.GetData(&(pixels[0]), &(alpha[0]));
01171 WriteImage2(type, pixels, alpha, bufferConfigs[i].postfix);
01172 }
01173 }
01174
01175 float Y = 0.f;
01176
01177
01178
01179 fill(pixels.begin(), pixels.end(), XYZColor(0.f));
01180 fill(alpha.begin(), alpha.end(), 0.f);
01181
01182 XYZColor p;
01183 float a;
01184
01185
01186 for(u_int j = 0; j < bufferGroups.size(); ++j) {
01187 if (!bufferGroups[j].enable)
01188 continue;
01189
01190 for(u_int i = 0; i < bufferConfigs.size(); ++i) {
01191 const Buffer &buffer = *(bufferGroups[j].buffers[i]);
01192 if (!(bufferConfigs[i].output & BUF_FRAMEBUFFER))
01193 continue;
01194
01195 for (int offset = 0, y = 0; y < yPixelCount; ++y) {
01196 for (int x = 0; x < xPixelCount; ++x,++offset) {
01197
01198 alphaWeight[offset] += buffer.GetData(x, y, &p, &a);
01199
01200 pixels[offset] += p * bufferGroups[j].scale;
01201 alpha[offset] += a;
01202 }
01203 }
01204 }
01205 }
01206
01207 for (int pix = 0; pix < nPix; ++pix) {
01208 if (alphaWeight[pix] > 0.f)
01209 alpha[pix] /= alphaWeight[pix];
01210 Y += pixels[pix].c[1];
01211 }
01212 Y /= nPix;
01213 WriteImage2(type, pixels, alpha, "");
01214 EV = logf(Y * 10.f) / logf(2.f);
01215 }
01216
01217
01218 void FlexImageFilm::createFrameBuffer()
01219 {
01220
01221 unsigned int nPix = xPixelCount * yPixelCount;
01222 framebuffer = new unsigned char[3*nPix];
01223
01224
01225 memset(framebuffer,0,sizeof(*framebuffer)*3*nPix);
01226 }
01227 void FlexImageFilm::updateFrameBuffer()
01228 {
01229 if(!framebuffer) {
01230 createFrameBuffer();
01231 }
01232
01233 WriteImage(IMAGE_FRAMEBUFFER);
01234 }
01235 unsigned char* FlexImageFilm::getFrameBuffer()
01236 {
01237 if(!framebuffer)
01238 createFrameBuffer();
01239
01240 return framebuffer;
01241 }
01242
01243 void FlexImageFilm::WriteResumeFilm(const string &filename)
01244 {
01245
01246 luxError(LUX_NOERROR, LUX_INFO, (std::string("Writing film status to file ") +
01247 filename).c_str());
01248
01249 std::ofstream filestr(filename.c_str(), std::ios_base::out | std::ios_base::binary);
01250 if(!filestr) {
01251 std::stringstream ss;
01252 ss << "Cannot open file '" << filename << "' for writing resume film";
01253 luxError(LUX_SYSTEM, LUX_SEVERE, ss.str().c_str());
01254
01255 return;
01256 }
01257
01258 TransmitFilm(filestr,false,true);
01259
01260 filestr.close();
01261 }
01262
01263 void FlexImageFilm::WriteTGAImage(vector<RGBColor> &rgb, vector<float> &alpha, const string &filename)
01264 {
01265
01266 luxError(LUX_NOERROR, LUX_INFO, (std::string("Writing Tonemapped TGA image to file ")+filename).c_str());
01267 WriteTargaImage(write_TGA_channels, write_TGA_ZBuf, filename, rgb, alpha,
01268 xPixelCount, yPixelCount,
01269 xResolution, yResolution,
01270 xPixelStart, yPixelStart);
01271 }
01272
01273 void FlexImageFilm::WritePNGImage(vector<RGBColor> &rgb, vector<float> &alpha, const string &filename)
01274 {
01275
01276 luxError(LUX_NOERROR, LUX_INFO, (std::string("Writing Tonemapped PNG image to file ")+filename).c_str());
01277 WritePngImage(write_PNG_channels, write_PNG_16bit, write_PNG_ZBuf, filename, rgb, alpha,
01278 xPixelCount, yPixelCount,
01279 xResolution, yResolution,
01280 xPixelStart, yPixelStart, colorSpace, m_Gamma);
01281 }
01282
01283 void FlexImageFilm::WriteEXRImage(vector<RGBColor> &rgb, vector<float> &alpha, const string &filename, vector<float> &zbuf)
01284 {
01285
01286 if(write_EXR_ZBuf) {
01287 if(write_EXR_ZBuf_normalizationtype == CameraStartEnd) {
01288
01289 } else if(write_EXR_ZBuf_normalizationtype == MinMax) {
01290
01291 const u_int nPix = xPixelCount * yPixelCount;
01292 float min = 0.f;
01293 float max = INFINITY;
01294 for(u_int i=0; i<nPix; i++) {
01295 if(zbuf[i] > 0.f) {
01296 if(zbuf[i] > min) min = zbuf[i];
01297 if(zbuf[i] < max) max = zbuf[i];
01298 }
01299 }
01300
01301 vector<float> zBuf(nPix);
01302 for (u_int i=0; i<nPix; i++)
01303 zBuf[i] = (zbuf[i]-min) / (max-min);
01304
01305 luxError(LUX_NOERROR, LUX_INFO, (std::string("Writing OpenEXR image to file ")+filename).c_str());
01306 WriteOpenEXRImage(write_EXR_channels, write_EXR_halftype, write_EXR_ZBuf, write_EXR_compressiontype, filename, rgb, alpha,
01307 xPixelCount, yPixelCount,
01308 xResolution, yResolution,
01309 xPixelStart, yPixelStart, zBuf);
01310 return;
01311 }
01312 }
01313
01314
01315 luxError(LUX_NOERROR, LUX_INFO, (std::string("Writing OpenEXR image to file ")+filename).c_str());
01316 WriteOpenEXRImage(write_EXR_channels, write_EXR_halftype, write_EXR_ZBuf, write_EXR_compressiontype, filename, rgb, alpha,
01317 xPixelCount, yPixelCount,
01318 xResolution, yResolution,
01319 xPixelStart, yPixelStart, zbuf);
01320 }
01321
01363 static const int FLM_MAGIC_NUMBER = 0xCEBCD816;
01364 static const int FLM_VERSION = 0;
01365 enum FlmParameterType {
01366 FLM_PARAMETER_TYPE_FLOAT = 0,
01367 FLM_PARAMETER_TYPE_STRING = 1
01368 };
01369
01370 class FlmParameter {
01371 public:
01372 FlmParameter() {}
01373 FlmParameter(FlexImageFilm *aFilm, FlmParameterType aType, luxComponentParameters aParam, int aIndex) {
01374 type = aType;
01375 id = (int)aParam;
01376 index = aIndex;
01377 switch(type) {
01378 case FLM_PARAMETER_TYPE_FLOAT:
01379 size = 4;
01380 floatValue = (float)aFilm->GetParameterValue(aParam, aIndex);
01381 break;
01382 case FLM_PARAMETER_TYPE_STRING:
01383 stringValue = aFilm->GetStringParameterValue(aParam, aIndex);
01384 size = (int)stringValue.size();
01385 break;
01386 default:
01387 {
01388 std::stringstream ss;
01389 ss << "Invalid parameter type (expected value in [0,1], got=" << type << ")";
01390 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str() );
01391 }
01392 break;
01393 }
01394 }
01395
01396 void Set(FlexImageFilm *aFilm) {
01397 switch(type) {
01398 case FLM_PARAMETER_TYPE_FLOAT:
01399 aFilm->SetParameterValue(luxComponentParameters(id), (double) floatValue, index);
01400 break;
01401 case FLM_PARAMETER_TYPE_STRING:
01402 aFilm->SetStringParameterValue(luxComponentParameters(id), stringValue, index);
01403 break;
01404 default:
01405
01406 break;
01407 }
01408 }
01409
01410 bool Read(std::basic_istream<char> &is, bool isLittleEndian, FlexImageFilm *film ) {
01411 int tmpType;
01412 tmpType = osReadLittleEndianInt(isLittleEndian, is);
01413 type = FlmParameterType(tmpType);
01414 if (!is.good()) {
01415 luxError(LUX_SYSTEM, LUX_ERROR, "Error while receiving film");
01416 return false;
01417 }
01418 if( type < 0 || type > 1 ) {
01419 std::stringstream ss;
01420 ss << "Invalid parameter type (expected value in [0,1], received=" << tmpType << ")";
01421 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str() );
01422 return false;
01423 }
01424 size = osReadLittleEndianInt(isLittleEndian, is);
01425 if (!is.good()) {
01426 luxError(LUX_SYSTEM, LUX_ERROR, "Error while receiving film");
01427 return false;
01428 }
01429 if( size < 0 || size > 1024 ) {
01430 std::stringstream ss;
01431 ss << "Invalid parameter size (expected value in [0,1024], received=" << size << ")";
01432 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str() );
01433 return false;
01434 }
01435 id = osReadLittleEndianInt(isLittleEndian, is);
01436 if (!is.good()) {
01437 luxError(LUX_SYSTEM, LUX_ERROR, "Error while receiving film");
01438 return false;
01439 }
01440 index = osReadLittleEndianInt(isLittleEndian, is);
01441 if (!is.good()) {
01442 luxError(LUX_SYSTEM, LUX_ERROR, "Error while receiving film");
01443 return false;
01444 }
01445 if( index < 0 ) {
01446 std::stringstream ss;
01447 ss << "Invalid parameter index (expected positive value, received=" << index << ")";
01448 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str() );
01449 return false;
01450 }
01451 switch(type) {
01452 case FLM_PARAMETER_TYPE_FLOAT:
01453 floatValue = osReadLittleEndianFloat(isLittleEndian, is);
01454 break;
01455 case FLM_PARAMETER_TYPE_STRING:
01456 {
01457 char* chars = new char[size+1];
01458 is.read(chars, size);
01459 chars[size] = '\0';
01460 stringValue = string(chars);
01461 delete[] chars;
01462 }
01463 break;
01464 default:
01465 return false;
01466 }
01467 return true;
01468 }
01469 void Write(std::basic_ostream<char> &os, bool isLittleEndian) const {
01470 osWriteLittleEndianInt(isLittleEndian, os, type);
01471 osWriteLittleEndianInt(isLittleEndian, os, size);
01472 osWriteLittleEndianInt(isLittleEndian, os, id);
01473 osWriteLittleEndianInt(isLittleEndian, os, index);
01474 switch(type) {
01475 case FLM_PARAMETER_TYPE_FLOAT:
01476 osWriteLittleEndianFloat(isLittleEndian, os, floatValue);
01477 break;
01478 case FLM_PARAMETER_TYPE_STRING:
01479 os.write(stringValue.c_str(), size);
01480 break;
01481 default:
01482
01483 break;
01484 }
01485 }
01486
01487 private:
01488 FlmParameterType type;
01489 int size;
01490 int id;
01491 int index;
01492
01493 float floatValue;
01494 string stringValue;
01495 };
01496
01497 class FlmHeader {
01498 public:
01499 FlmHeader() {}
01500 bool Read(filtering_stream<input> &in, bool isLittleEndian, FlexImageFilm *film );
01501 void Write(std::basic_ostream<char> &os, bool isLittleEndian) const;
01502
01503 int magicNumber;
01504 int versionNumber;
01505 int xResolution;
01506 int yResolution;
01507 u_int numBufferGroups;
01508 u_int numBufferConfigs;
01509 vector<int> bufferTypes;
01510 u_int numParams;
01511 vector<FlmParameter> params;
01512 };
01513
01514 bool FlmHeader::Read(filtering_stream<input> &in, bool isLittleEndian, FlexImageFilm *film ) {
01515
01516 magicNumber = osReadLittleEndianInt(isLittleEndian, in);
01517 if (!in.good()) {
01518 luxError(LUX_SYSTEM, LUX_ERROR, "Error while receiving film");
01519 return false;
01520 }
01521 if (magicNumber != FLM_MAGIC_NUMBER) {
01522 std::stringstream ss;
01523 ss << "Invalid FLM magic number (expected=" << FLM_MAGIC_NUMBER
01524 << ", received=" << magicNumber << ")";
01525 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str());
01526 return false;
01527 }
01528 versionNumber = osReadLittleEndianInt(isLittleEndian, in);
01529 if (!in.good()) {
01530 luxError(LUX_SYSTEM, LUX_ERROR, "Error while receiving film");
01531 return false;
01532 }
01533 if (versionNumber != FLM_VERSION) {
01534 std::stringstream ss;
01535 ss << "Invalid FLM version (expected=" << FLM_VERSION
01536 << ", received=" << versionNumber << ")";
01537 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str());
01538 return false;
01539 }
01540
01541 xResolution = osReadLittleEndianInt(isLittleEndian, in);
01542 yResolution = osReadLittleEndianInt(isLittleEndian, in);
01543 if (xResolution <= 0 || yResolution <= 0 ) {
01544 std::stringstream ss;
01545 ss << "Invalid resolution (expected positive resolution, received=" << xResolution << "x" << yResolution << ")";
01546 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str());
01547 return false;
01548 }
01549 if (film != NULL &&
01550 (xResolution != film->GetXPixelCount() ||
01551 yResolution != film->GetYPixelCount())) {
01552 std::stringstream ss;
01553 ss << "Invalid resolution (expected=" << film->GetXPixelCount() << "x" << film->GetYPixelCount();
01554 ss << ", received=" << xResolution << "x" << yResolution << ")";
01555 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str());
01556 return false;
01557 }
01558
01559 numBufferGroups = osReadLittleEndianUInt(isLittleEndian, in);
01560 if (!in.good()) {
01561 luxError(LUX_SYSTEM, LUX_ERROR, "Error while receiving film");
01562 return false;
01563 }
01564 if (film != NULL && numBufferGroups != film->GetNumBufferGroups()) {
01565 std::stringstream ss;
01566 ss << "Invalid number of buffer groups (expected=" << film->GetNumBufferGroups()
01567 << ", received=" << numBufferGroups << ")";
01568 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str());
01569 return false;
01570 }
01571 numBufferConfigs = osReadLittleEndianUInt(isLittleEndian, in);
01572 if (!in.good()) {
01573 luxError(LUX_SYSTEM, LUX_ERROR, "Error while receiving film");
01574 return false;
01575 }
01576 if (film != NULL && numBufferConfigs != film->GetNumBufferConfigs()) {
01577 std::stringstream ss;
01578 ss << "Invalid number of buffers (expected=" << film->GetNumBufferConfigs()
01579 << ", received=" << numBufferConfigs << ")";
01580 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str());
01581 return false;
01582 }
01583 for (u_int i = 0; i < numBufferConfigs; ++i) {
01584 int type;
01585 type = osReadLittleEndianInt(isLittleEndian, in);
01586 if (!in.good()) {
01587 luxError(LUX_SYSTEM, LUX_ERROR, "Error while receiving film");
01588 return false;
01589 }
01590 if (type < 0 || type >= NUM_OF_BUFFER_TYPES) {
01591 std::stringstream ss;
01592 ss << "Invalid buffer type for buffer " << i << "(expected number in [0," << NUM_OF_BUFFER_TYPES << "[, received=" << type << ")";
01593 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str());
01594 return false;
01595 }
01596 if (film != NULL && type != film->GetBufferConfig(i).type) {
01597 std::stringstream ss;
01598 ss << "Invalid buffer type for buffer " << i << " (expected=" << film->GetBufferConfig(i).type
01599 << ", received=" << type << ")";
01600 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str());
01601 return false;
01602 }
01603 bufferTypes.push_back(type);
01604 }
01605
01606 numParams = osReadLittleEndianUInt(isLittleEndian, in);
01607 if (!in.good()) {
01608 luxError(LUX_SYSTEM, LUX_ERROR, "Error while receiving film");
01609 return false;
01610 }
01611 params.reserve(numParams);
01612 for(u_int i = 0; i < numParams; ++i) {
01613 FlmParameter param;
01614 bool ok = param.Read(in, isLittleEndian, film);
01615 if (!in.good()) {
01616 luxError(LUX_SYSTEM, LUX_ERROR, "Error while receiving film");
01617 return false;
01618 }
01619 if(!ok) {
01620
01621
01622
01623 return false;
01624 }
01625 params.push_back(param);
01626 }
01627 return true;
01628 }
01629
01630 void FlmHeader::Write(std::basic_ostream<char> &os, bool isLittleEndian) const
01631 {
01632
01633 osWriteLittleEndianInt(isLittleEndian, os, magicNumber);
01634 osWriteLittleEndianInt(isLittleEndian, os, versionNumber);
01635
01636 osWriteLittleEndianInt(isLittleEndian, os, xResolution);
01637 osWriteLittleEndianInt(isLittleEndian, os, yResolution);
01638
01639 osWriteLittleEndianUInt(isLittleEndian, os, numBufferGroups);
01640 osWriteLittleEndianUInt(isLittleEndian, os, numBufferConfigs);
01641 for (u_int i = 0; i < numBufferConfigs; ++i)
01642 osWriteLittleEndianInt(isLittleEndian, os, bufferTypes[i]);
01643
01644 osWriteLittleEndianUInt(isLittleEndian, os, numParams);
01645 for(u_int i = 0; i < numParams; ++i) {
01646 params[i].Write(os, isLittleEndian);
01647 }
01648 }
01649
01650 void FlexImageFilm::TransmitFilm(
01651 std::basic_ostream<char> &stream,
01652 bool clearBuffers,
01653 bool transmitParams)
01654 {
01655 const bool isLittleEndian = osIsLittleEndian();
01656
01657 std::stringstream ss;
01658 ss << "Transmitting film (little endian=" <<(isLittleEndian ? "true" : "false") << ")";
01659 luxError(LUX_NOERROR, LUX_DEBUG, ss.str().c_str());
01660
01661 std::stringstream os;
01662
01663 FlmHeader header;
01664 header.magicNumber = FLM_MAGIC_NUMBER;
01665 header.versionNumber = FLM_VERSION;
01666 header.xResolution = GetXPixelCount();
01667 header.yResolution = GetYPixelCount();
01668 header.numBufferGroups = bufferGroups.size();
01669 header.numBufferConfigs = bufferConfigs.size();
01670 for (u_int i = 0; i < bufferConfigs.size(); ++i)
01671 header.bufferTypes.push_back(bufferConfigs[i].type);
01672
01673 if (transmitParams) {
01674 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TM_TONEMAPKERNEL, 0));
01675
01676 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TM_REINHARD_PRESCALE, 0));
01677 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TM_REINHARD_POSTSCALE, 0));
01678 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TM_REINHARD_BURN, 0));
01679
01680 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TM_LINEAR_SENSITIVITY, 0));
01681 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TM_LINEAR_EXPOSURE, 0));
01682 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TM_LINEAR_FSTOP, 0));
01683 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TM_LINEAR_GAMMA, 0));
01684
01685 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TM_CONTRAST_YWA, 0));
01686
01687 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TORGB_X_WHITE, 0));
01688 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TORGB_Y_WHITE, 0));
01689 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TORGB_X_RED, 0));
01690 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TORGB_Y_RED, 0));
01691 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TORGB_X_GREEN, 0));
01692 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TORGB_Y_GREEN, 0));
01693 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TORGB_X_BLUE, 0));
01694 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TORGB_Y_BLUE, 0));
01695 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_TORGB_GAMMA, 0));
01696
01697
01698 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_UPDATEBLOOMLAYER, 0));
01699 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_DELETEBLOOMLAYER, 0));
01700 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_BLOOMRADIUS, 0));
01701 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_BLOOMWEIGHT, 0));
01702
01703 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_VIGNETTING_ENABLED, 0));
01704 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_VIGNETTING_SCALE, 0));
01705
01706 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_ABERRATION_ENABLED, 0));
01707 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_ABERRATION_AMOUNT, 0));
01708
01709 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_UPDATEGLARELAYER, 0));
01710 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_DELETEGLARELAYER, 0));
01711 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_GLARE_AMOUNT, 0));
01712 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_GLARE_RADIUS, 0));
01713 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_GLARE_BLADES, 0));
01714
01715 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_CHIU_ENABLED, 0));
01716 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_CHIU_RADIUS, 0));
01717 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_CHIU_INCLUDECENTER, 0));
01718
01719 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_ENABLED, 0));
01720 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_AMPLITUDE, 0));
01721 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_NBITER, 0));
01722 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_SHARPNESS, 0));
01723 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_ANISOTROPY, 0));
01724 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_ALPHA, 0));
01725 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_SIGMA, 0));
01726 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_FASTAPPROX, 0));
01727 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_GAUSSPREC, 0));
01728 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_DL, 0));
01729 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_DA, 0));
01730 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_INTERP, 0));
01731 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_TILE, 0));
01732 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_BTILE, 0));
01733 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_NOISE_GREYC_THREADS, 0));
01734
01735 for(u_int i = 0; i < GetNumBufferGroups(); ++i) {
01736 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_LG_SCALE, int(i)));
01737 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_LG_ENABLE, int(i)));
01738 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_LG_SCALE_RED, int(i)));
01739 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_LG_SCALE_GREEN, int(i)));
01740 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_LG_SCALE_BLUE, int(i)));
01741 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_FLOAT, LUX_FILM_LG_TEMPERATURE, int(i)));
01742
01743 header.params.push_back(FlmParameter(this, FLM_PARAMETER_TYPE_STRING, LUX_FILM_LG_NAME, int(i)));
01744 }
01745
01746 header.numParams = header.params.size();
01747 } else {
01748 header.numParams = 0;
01749 }
01750 header.Write(os, isLittleEndian);
01751
01752
01753 float totNumberOfSamples = 0.f;
01754 for (u_int i = 0; i < bufferGroups.size(); ++i) {
01755 BufferGroup& bufferGroup = bufferGroups[i];
01756
01757 osWriteLittleEndianDouble(isLittleEndian, os, bufferGroup.numberOfSamples);
01758
01759
01760 for (u_int j = 0; j < bufferConfigs.size(); ++j) {
01761 Buffer* buffer = bufferGroup.getBuffer(j);
01762
01763
01764 const BlockedArray<Pixel>* pixelBuf = buffer->pixels;
01765 for (int y = 0; y < pixelBuf->vSize(); ++y) {
01766 for (int x = 0; x < pixelBuf->uSize(); ++x) {
01767 const Pixel &pixel = (*pixelBuf)(x, y);
01768 osWriteLittleEndianFloat(isLittleEndian, os, pixel.L.c[0]);
01769 osWriteLittleEndianFloat(isLittleEndian, os, pixel.L.c[1]);
01770 osWriteLittleEndianFloat(isLittleEndian, os, pixel.L.c[2]);
01771 osWriteLittleEndianFloat(isLittleEndian, os, pixel.alpha);
01772 osWriteLittleEndianFloat(isLittleEndian, os, pixel.weightSum);
01773 }
01774 }
01775
01776 if (clearBuffers) {
01777
01778 buffer->Clear();
01779 }
01780 }
01781
01782 totNumberOfSamples += bufferGroup.numberOfSamples;
01783 ss.str("");
01784 ss << "Transmitted " << bufferGroup.numberOfSamples << " samples for buffer group " << i <<
01785 " (buffer config size: " << bufferConfigs.size() << ")";
01786 luxError(LUX_NOERROR, LUX_DEBUG, ss.str().c_str());
01787
01788 if (clearBuffers) {
01789
01790 bufferGroup.numberOfSamples = 0;
01791 }
01792 }
01793
01794 if (!os.good()) {
01795 luxError(LUX_SYSTEM, LUX_SEVERE, "Error while preparing film data for transmission");
01796 return;
01797 }
01798
01799 ss.str("");
01800 ss << "Transmitted a film with " << totNumberOfSamples << " samples";
01801 luxError(LUX_NOERROR, LUX_DEBUG, ss.str().c_str());
01802
01803 filtering_streambuf<input> in;
01804 in.push(gzip_compressor(9));
01805 in.push(os);
01806 std::streamsize size = boost::iostreams::copy(in, stream);
01807 if (!stream.good()) {
01808 luxError(LUX_SYSTEM, LUX_SEVERE, "Error while transmitting film");
01809 return;
01810 }
01811
01812 ss.str("");
01813 ss << "Film transmission done (" << (size / 1024) << " Kbytes sent)";
01814 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
01815 }
01816
01817 float FlexImageFilm::UpdateFilm(std::basic_istream<char> &stream) {
01818 const bool isLittleEndian = osIsLittleEndian();
01819
01820 filtering_stream<input> in;
01821 in.push(gzip_decompressor());
01822 in.push(stream);
01823
01824 std::stringstream ss;
01825 ss << "Receiving film (little endian=" << (isLittleEndian ? "true" : "false") << ")";
01826 luxError(LUX_NOERROR, LUX_DEBUG, ss.str().c_str());
01827
01828
01829 FlmHeader header;
01830 if (!header.Read(in, isLittleEndian, this))
01831 return 0.f;
01832
01833
01834 vector<float> bufferGroupNumSamples(bufferGroups.size());
01835 vector<BlockedArray<Pixel>*> tmpPixelArrays(bufferGroups.size() * bufferConfigs.size());
01836 for (u_int i = 0; i < bufferGroups.size(); i++) {
01837 double numberOfSamples;
01838 numberOfSamples = osReadLittleEndianDouble(isLittleEndian, in);
01839 if (!in.good())
01840 break;
01841 bufferGroupNumSamples[i] = numberOfSamples;
01842
01843
01844 for(u_int j = 0; j < bufferConfigs.size(); ++j) {
01845 const Buffer* localBuffer = bufferGroups[i].getBuffer(j);
01846
01847 BlockedArray<Pixel> *tmpPixelArr = new BlockedArray<Pixel>(
01848 localBuffer->xPixelCount, localBuffer->yPixelCount);
01849 tmpPixelArrays[i*bufferConfigs.size() + j] = tmpPixelArr;
01850 for (int y = 0; y < tmpPixelArr->vSize(); ++y) {
01851 for (int x = 0; x < tmpPixelArr->uSize(); ++x) {
01852 Pixel &pixel = (*tmpPixelArr)(x, y);
01853 pixel.L.c[0] = osReadLittleEndianFloat(isLittleEndian, in);
01854 pixel.L.c[1] = osReadLittleEndianFloat(isLittleEndian, in);
01855 pixel.L.c[2] = osReadLittleEndianFloat(isLittleEndian, in);
01856 pixel.alpha = osReadLittleEndianFloat(isLittleEndian, in);
01857 pixel.weightSum = osReadLittleEndianFloat(isLittleEndian, in);
01858 }
01859 }
01860 if (!in.good())
01861 break;
01862 }
01863 if (!in.good())
01864 break;
01865
01866 ss.str("");
01867 ss << "Received " << bufferGroupNumSamples[i] << " samples for buffer group " << i <<
01868 " (buffer config size: " << bufferConfigs.size() << ")";
01869 luxError(LUX_NOERROR, LUX_DEBUG, ss.str().c_str());
01870 }
01871
01872
01873 float totNumberOfSamples = 0.f;
01874 float maxTotNumberOfSamples = 0.f;
01875 if (in.good()) {
01876
01877 for (vector<FlmParameter>::iterator it = header.params.begin(); it != header.params.end(); ++it)
01878 it->Set(this);
01879
01880
01881 for (u_int i = 0; i < bufferGroups.size(); ++i) {
01882 BufferGroup ¤tGroup = bufferGroups[i];
01883 for (u_int j = 0; j < bufferConfigs.size(); ++j) {
01884 const BlockedArray<Pixel> *receivedPixels = tmpPixelArrays[ i * bufferConfigs.size() + j ];
01885 Buffer *buffer = currentGroup.getBuffer(j);
01886
01887 for (int y = 0; y < buffer->yPixelCount; ++y) {
01888 for (int x = 0; x < buffer->xPixelCount; ++x) {
01889 const Pixel &pixel = (*receivedPixels)(x, y);
01890 Pixel &pixelResult = (*buffer->pixels)(x, y);
01891
01892 pixelResult.L.c[0] += pixel.L.c[0];
01893 pixelResult.L.c[1] += pixel.L.c[1];
01894 pixelResult.L.c[2] += pixel.L.c[2];
01895 pixelResult.alpha += pixel.alpha;
01896 pixelResult.weightSum += pixel.weightSum;
01897 }
01898 }
01899 }
01900
01901 currentGroup.numberOfSamples += bufferGroupNumSamples[i];
01902
01903 if ((haltSamplePerPixel > 0) &&
01904 (currentGroup.numberOfSamples >= haltSamplePerPixel * samplePerPass))
01905 enoughSamplePerPixel = true;
01906 totNumberOfSamples += bufferGroupNumSamples[i];
01907 maxTotNumberOfSamples = max(maxTotNumberOfSamples, bufferGroupNumSamples[i]);
01908 }
01909
01910 if (scene != NULL)
01911 scene->numberOfSamplesFromNetwork += maxTotNumberOfSamples;
01912
01913 ss.str("");
01914 ss << "Received film with " << totNumberOfSamples << " samples";
01915 luxError(LUX_NOERROR, LUX_DEBUG, ss.str().c_str());
01916 } else
01917 luxError(LUX_SYSTEM, LUX_ERROR, "IO error while receiving film buffers");
01918
01919
01920 for (u_int i = 0; i < tmpPixelArrays.size(); ++i)
01921 delete tmpPixelArrays[i];
01922
01923 return maxTotNumberOfSamples;
01924 }
01925
01926 void FlexImageFilm::GetColorspaceParam(const ParamSet ¶ms, const string name, float values[2]) {
01927 int i;
01928 const float *v = params.FindFloat(name, &i);
01929 if (v && i == 2) {
01930 values[0] = v[0];
01931 values[1] = v[1];
01932 }
01933 }
01934
01935
01936 Film* FlexImageFilm::CreateFilm(const ParamSet ¶ms, Filter *filter)
01937 {
01938
01939 bool premultiplyAlpha = params.FindOneBool("premultiplyalpha", false);
01940
01941 int xres = params.FindOneInt("xresolution", 800);
01942 int yres = params.FindOneInt("yresolution", 600);
01943
01944 float crop[4] = { 0, 1, 0, 1 };
01945 int cwi;
01946 const float *cr = params.FindFloat("cropwindow", &cwi);
01947 if (cr && cwi == 4) {
01948 crop[0] = Clamp(min(cr[0], cr[1]), 0.f, 1.f);
01949 crop[1] = Clamp(max(cr[0], cr[1]), 0.f, 1.f);
01950 crop[2] = Clamp(min(cr[2], cr[3]), 0.f, 1.f);
01951 crop[3] = Clamp(max(cr[2], cr[3]), 0.f, 1.f);
01952 }
01953
01954
01955 string clampMethodString = params.FindOneString("ldr_clamp_method", "lum");
01956 int clampMethod = 0;
01957 if (clampMethodString == "lum")
01958 clampMethod = 0;
01959 else if (clampMethodString == "hue")
01960 clampMethod = 1;
01961 else if (clampMethodString == "cut")
01962 clampMethod = 2;
01963 else {
01964 std::stringstream ss;
01965 ss << "LDR clamping method '" << clampMethodString << "' unknown. Using \"lum\".";
01966 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
01967 }
01968
01969
01970 bool w_EXR = params.FindOneBool("write_exr", false);
01971
01972 OutputChannels w_EXR_channels = RGB;
01973 string w_EXR_channelsStr = params.FindOneString("write_exr_channels", "RGB");
01974 if (w_EXR_channelsStr == "Y") w_EXR_channels = Y;
01975 else if (w_EXR_channelsStr == "YA") w_EXR_channels = YA;
01976 else if (w_EXR_channelsStr == "RGB") w_EXR_channels = RGB;
01977 else if (w_EXR_channelsStr == "RGBA") w_EXR_channels = RGBA;
01978 else {
01979 std::stringstream ss;
01980 ss << "OpenEXR Output Channels '" << w_EXR_channelsStr << "' unknown. Using \"RGB\".";
01981 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
01982 w_EXR_channels = RGB;
01983 }
01984
01985 bool w_EXR_halftype = params.FindOneBool("write_exr_halftype", true);
01986
01987 int w_EXR_compressiontype = 1;
01988 string w_EXR_compressiontypeStr = params.FindOneString("write_exr_compressiontype", "PIZ (lossless)");
01989 if (w_EXR_compressiontypeStr == "RLE (lossless)") w_EXR_compressiontype = 0;
01990 else if (w_EXR_compressiontypeStr == "PIZ (lossless)") w_EXR_compressiontype = 1;
01991 else if (w_EXR_compressiontypeStr == "ZIP (lossless)") w_EXR_compressiontype = 2;
01992 else if (w_EXR_compressiontypeStr == "Pxr24 (lossy)") w_EXR_compressiontype = 3;
01993 else if (w_EXR_compressiontypeStr == "None") w_EXR_compressiontype = 4;
01994 else {
01995 std::stringstream ss;
01996 ss << "OpenEXR Compression Type '" << w_EXR_compressiontypeStr << "' unknown. Using \"PIZ (lossless)\".";
01997 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
01998 w_EXR_compressiontype = 1;
01999 }
02000
02001 bool w_EXR_applyimaging = params.FindOneBool("write_exr_applyimaging", true);
02002 bool w_EXR_gamutclamp = params.FindOneBool("write_exr_gamutclamp", true);
02003
02004 bool w_EXR_ZBuf = params.FindOneBool("write_exr_ZBuf", false);
02005
02006 ZBufNormalization w_EXR_ZBuf_normalizationtype = None;
02007 string w_EXR_ZBuf_normalizationtypeStr = params.FindOneString("write_exr_zbuf_normalizationtype", "None");
02008 if (w_EXR_ZBuf_normalizationtypeStr == "None") w_EXR_ZBuf_normalizationtype = None;
02009 else if (w_EXR_ZBuf_normalizationtypeStr == "Camera Start/End clip") w_EXR_ZBuf_normalizationtype = CameraStartEnd;
02010 else if (w_EXR_ZBuf_normalizationtypeStr == "Min/Max") w_EXR_ZBuf_normalizationtype = MinMax;
02011 else {
02012 std::stringstream ss;
02013 ss << "OpenEXR ZBuf Normalization Type '" << w_EXR_ZBuf_normalizationtypeStr << "' unknown. Using \"None\".";
02014 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
02015 w_EXR_ZBuf_normalizationtype = None;
02016 }
02017
02018
02019 bool w_PNG = params.FindOneBool("write_png", true);
02020
02021 OutputChannels w_PNG_channels = RGB;
02022 string w_PNG_channelsStr = params.FindOneString("write_png_channels", "RGB");
02023 if (w_PNG_channelsStr == "Y") w_PNG_channels = Y;
02024 else if (w_PNG_channelsStr == "YA") w_PNG_channels = YA;
02025 else if (w_PNG_channelsStr == "RGB") w_PNG_channels = RGB;
02026 else if (w_PNG_channelsStr == "RGBA") w_PNG_channels = RGBA;
02027 else {
02028 std::stringstream ss;
02029 ss << "PNG Output Channels '" << w_PNG_channelsStr << "' unknown. Using \"RGB\".";
02030 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
02031 w_PNG_channels = RGB;
02032 }
02033
02034 bool w_PNG_16bit = params.FindOneBool("write_png_16bit", false);
02035 bool w_PNG_gamutclamp = params.FindOneBool("write_png_gamutclamp", true);
02036
02037 bool w_PNG_ZBuf = params.FindOneBool("write_png_ZBuf", false);
02038
02039 ZBufNormalization w_PNG_ZBuf_normalizationtype = MinMax;
02040 string w_PNG_ZBuf_normalizationtypeStr = params.FindOneString("write_png_zbuf_normalizationtype", "Min/Max");
02041 if (w_PNG_ZBuf_normalizationtypeStr == "None") w_PNG_ZBuf_normalizationtype = None;
02042 else if (w_PNG_ZBuf_normalizationtypeStr == "Camera Start/End clip") w_PNG_ZBuf_normalizationtype = CameraStartEnd;
02043 else if (w_PNG_ZBuf_normalizationtypeStr == "Min/Max") w_PNG_ZBuf_normalizationtype = MinMax;
02044 else {
02045 std::stringstream ss;
02046 ss << "PNG ZBuf Normalization Type '" << w_PNG_ZBuf_normalizationtypeStr << "' unknown. Using \"Min/Max\".";
02047 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
02048 w_PNG_ZBuf_normalizationtype = MinMax;
02049 }
02050
02051
02052 bool w_TGA = params.FindOneBool("write_tga", false);
02053
02054 OutputChannels w_TGA_channels = RGB;
02055 string w_TGA_channelsStr = params.FindOneString("write_tga_channels", "RGB");
02056 if (w_TGA_channelsStr == "Y") w_TGA_channels = Y;
02057 else if (w_TGA_channelsStr == "RGB") w_TGA_channels = RGB;
02058 else if (w_TGA_channelsStr == "RGBA") w_TGA_channels = RGBA;
02059 else {
02060 std::stringstream ss;
02061 ss << "TGA Output Channels '" << w_TGA_channelsStr << "' unknown. Using \"RGB\".";
02062 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
02063 w_TGA_channels = RGB;
02064 }
02065
02066 bool w_TGA_gamutclamp = params.FindOneBool("write_tga_gamutclamp", true);
02067
02068 bool w_TGA_ZBuf = params.FindOneBool("write_tga_ZBuf", false);
02069
02070 ZBufNormalization w_TGA_ZBuf_normalizationtype = MinMax;
02071 string w_TGA_ZBuf_normalizationtypeStr = params.FindOneString("write_tga_zbuf_normalizationtype", "Min/Max");
02072 if (w_TGA_ZBuf_normalizationtypeStr == "None") w_TGA_ZBuf_normalizationtype = None;
02073 else if (w_TGA_ZBuf_normalizationtypeStr == "Camera Start/End clip") w_TGA_ZBuf_normalizationtype = CameraStartEnd;
02074 else if (w_TGA_ZBuf_normalizationtypeStr == "Min/Max") w_TGA_ZBuf_normalizationtype = MinMax;
02075 else {
02076 std::stringstream ss;
02077 ss << "TGA ZBuf Normalization Type '" << w_TGA_ZBuf_normalizationtypeStr << "' unknown. Using \"Min/Max\".";
02078 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
02079 w_TGA_ZBuf_normalizationtype = MinMax;
02080 }
02081
02082
02083
02084 bool w_resume_FLM = params.FindOneBool("write_resume_flm", false);
02085 bool restart_resume_FLM = params.FindOneBool("restart_resume_flm", false);
02086
02087
02088 string filename = params.FindOneString("filename", "luxout");
02089
02090
02091 int writeInterval = params.FindOneInt("writeinterval", 60);
02092 int displayInterval = params.FindOneInt("displayinterval", 12);
02093
02094
02095 int reject_warmup = params.FindOneInt("reject_warmup", 64);
02096
02097
02098 bool debug_mode = params.FindOneBool("debug", false);
02099
02100 const int haltspp = params.FindOneInt("haltspp", -1);
02101 const int halttime = params.FindOneInt("halttime", -1);
02102
02103
02104
02105 float red[2] = {0.63f, 0.34f};
02106 GetColorspaceParam(params, "colorspace_red", red);
02107
02108 float green[2] = {0.31f, 0.595f};
02109 GetColorspaceParam(params, "colorspace_green", green);
02110
02111 float blue[2] = {0.155f, 0.07f};
02112 GetColorspaceParam(params, "colorspace_blue", blue);
02113
02114 float white[2] = {0.314275f, 0.329411f};
02115 GetColorspaceParam(params, "colorspace_white", white);
02116
02117
02118 int s_TonemapKernel = 0;
02119 string tmkernelStr = params.FindOneString("tonemapkernel", "reinhard");
02120 if (tmkernelStr == "reinhard") s_TonemapKernel = 0;
02121 else if (tmkernelStr == "linear") s_TonemapKernel = 1;
02122 else if (tmkernelStr == "contrast") s_TonemapKernel = 2;
02123 else if (tmkernelStr == "maxwhite") s_TonemapKernel = 3;
02124 else {
02125 std::stringstream ss;
02126 ss << "Tonemap kernel '" << tmkernelStr << "' unknown. Using \"reinhard\".";
02127 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
02128 s_TonemapKernel = 0;
02129 }
02130
02131 float s_ReinhardPreScale = params.FindOneFloat("reinhard_prescale", 1.f);
02132 float s_ReinhardPostScale = params.FindOneFloat("reinhard_postscale", 1.f);
02133 float s_ReinhardBurn = params.FindOneFloat("reinhard_burn", 6.f);
02134 float s_LinearSensitivity = params.FindOneFloat("linear_sensitivity", 50.f);
02135 float s_LinearExposure = params.FindOneFloat("linear_exposure", 1.f);
02136 float s_LinearFStop = params.FindOneFloat("linear_fstop", 2.8f);
02137 float s_LinearGamma = params.FindOneFloat("linear_gamma", 1.0f);
02138 float s_ContrastYwa = params.FindOneFloat("contrast_ywa", 1.f);
02139 float s_Gamma = params.FindOneFloat("gamma", 2.2f);
02140
02141 return new FlexImageFilm(xres, yres, filter, crop,
02142 filename, premultiplyAlpha, writeInterval, displayInterval,
02143 clampMethod, w_EXR, w_EXR_channels, w_EXR_halftype, w_EXR_compressiontype, w_EXR_applyimaging, w_EXR_gamutclamp, w_EXR_ZBuf, w_EXR_ZBuf_normalizationtype,
02144 w_PNG, w_PNG_channels, w_PNG_16bit, w_PNG_gamutclamp, w_PNG_ZBuf, w_PNG_ZBuf_normalizationtype,
02145 w_TGA, w_TGA_channels, w_TGA_gamutclamp, w_TGA_ZBuf, w_TGA_ZBuf_normalizationtype,
02146 w_resume_FLM, restart_resume_FLM, haltspp, halttime,
02147 s_TonemapKernel, s_ReinhardPreScale, s_ReinhardPostScale, s_ReinhardBurn, s_LinearSensitivity,
02148 s_LinearExposure, s_LinearFStop, s_LinearGamma, s_ContrastYwa, s_Gamma,
02149 red, green, blue, white, reject_warmup, debug_mode);
02150 }
02151
02152
02153 Film *FlexImageFilm::CreateFilmFromFLM(const string& flmFileName) {
02154
02155
02156 ParamSet dummyParams;
02157 Filter *dummyFilter = MakeFilter("box", dummyParams);
02158
02159
02160 std::ifstream stream(flmFileName.c_str(), std::ios_base::in | std::ios_base::binary);
02161 filtering_stream<input> in;
02162 in.push(gzip_decompressor());
02163 in.push(stream);
02164 const bool isLittleEndian = osIsLittleEndian();
02165 FlmHeader header;
02166 bool headerOk = header.Read(in, isLittleEndian, NULL);
02167 stream.close();
02168 if (!headerOk)
02169 return NULL;
02170
02171
02172 const string filename = flmFileName.substr(0, flmFileName.length() - 4);
02173 static const bool boolTrue = true;
02174 static const bool boolFalse = false;
02175 ParamSet filmParams;
02176 filmParams.AddString("filename", &filename );
02177 filmParams.AddInt("xresolution", &header.xResolution);
02178 filmParams.AddInt("yresolution", &header.yResolution);
02179 filmParams.AddBool("write_resume_flm", &boolTrue);
02180 filmParams.AddBool("restart_resume_flm", &boolFalse);
02181 filmParams.AddBool("write_exr", &boolFalse);
02182 filmParams.AddBool("write_exr_ZBuf", &boolFalse);
02183 filmParams.AddBool("write_png", &boolFalse);
02184 filmParams.AddBool("write_png_ZBuf", &boolFalse);
02185 filmParams.AddBool("write_tga", &boolFalse);
02186 filmParams.AddBool("write_tga_ZBuf", &boolFalse);
02187 Film *film = FlexImageFilm::CreateFilm(filmParams, dummyFilter);
02188
02189
02190 for (u_int i = 0; i < header.numBufferConfigs; ++i)
02191 film->RequestBuffer(BufferType(header.bufferTypes[i]), BUF_FRAMEBUFFER, "");
02192
02193 vector<string> bufferGroups;
02194 for (u_int i = 0; i < header.numBufferGroups; ++i) {
02195 std::stringstream ss;
02196 ss << "lightgroup #" << (i + 1);
02197 bufferGroups.push_back(ss.str());
02198 }
02199 film->RequestBufferGroups(bufferGroups);
02200 film->CreateBuffers();
02201
02202 return film;
02203 }
02204
02205 static DynamicLoader::RegisterFilm<FlexImageFilm> r1("fleximage");
02206 static DynamicLoader::RegisterFilm<FlexImageFilm> r2("multiimage");