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 "camera.h"
00032 #include "transport.h"
00033 #include "filter.h"
00034
00035 #include <iostream>
00036 #include <fstream>
00037
00038 #include <boost/thread/xtime.hpp>
00039 #include <boost/archive/text_oarchive.hpp>
00040 #include <boost/archive/text_iarchive.hpp>
00041 #include <boost/archive/binary_oarchive.hpp>
00042 #include <boost/archive/binary_iarchive.hpp>
00043 #include <boost/serialization/split_member.hpp>
00044 #include <boost/serialization/vector.hpp>
00045 #include <boost/serialization/string.hpp>
00046 #include <boost/iostreams/filtering_stream.hpp>
00047 #include <boost/iostreams/filtering_streambuf.hpp>
00048 #include <boost/iostreams/copy.hpp>
00049 #include <boost/iostreams/filter/zlib.hpp>
00050 #include <boost/iostreams/filter/bzip2.hpp>
00051 #include <boost/iostreams/filter/gzip.hpp>
00052
00053 using namespace boost::iostreams;
00054 using namespace lux;
00055
00056
00057 FlexImageFilm::FlexImageFilm(int xres, int yres, Filter *filt, const float crop[4],
00058 const string &filename1, bool premult, int wI, int dI,
00059 bool w_tonemapped_EXR, bool w_untonemapped_EXR, bool w_tonemapped_IGI,
00060 bool w_untonemapped_IGI, bool w_tonemapped_TGA, bool w_resume_FLM, bool restart_resume_FLM,
00061 int haltspp, float reinhard_prescale, float reinhard_postscale,
00062 float reinhard_burn, float g, int reject_warmup, bool debugmode) :
00063 Film(xres, yres, haltspp), filter(filt), writeInterval(wI), displayInterval(dI),
00064 filename(filename1), premultiplyAlpha(premult), buffersInited(false), gamma(g),
00065 writeTmExr(w_tonemapped_EXR), writeUtmExr(w_untonemapped_EXR), writeTmIgi(w_tonemapped_IGI),
00066 writeUtmIgi(w_untonemapped_IGI), writeTmTga(w_tonemapped_TGA), writeResumeFlm(w_resume_FLM), restartResumeFlm(restart_resume_FLM),
00067 framebuffer(NULL), debug_mode(debugmode), factor(NULL)
00068 {
00069
00070 memcpy(cropWindow, crop, 4 * sizeof(float));
00071 xPixelStart = Ceil2Int(xResolution * cropWindow[0]);
00072 xPixelCount = max(1, Ceil2Int(xResolution * cropWindow[1]) - xPixelStart);
00073 yPixelStart = Ceil2Int(yResolution * cropWindow[2]);
00074 yPixelCount = max(1, Ceil2Int(yResolution * cropWindow[3]) - yPixelStart);
00075
00076
00077 toneParams.AddFloat("prescale", &reinhard_prescale, 1);
00078 toneParams.AddFloat("postscale", &reinhard_postscale, 1);
00079 toneParams.AddFloat("burn", &reinhard_burn, 1);
00080
00081
00082 boost::xtime_get(&lastWriteImageTime, boost::TIME_UTC);
00083
00084
00085 reject_warmup_samples = (float) (xResolution * yResolution * reject_warmup);
00086
00087
00088 #define FILTER_TABLE_SIZE 16
00089 filterTable = new float[FILTER_TABLE_SIZE * FILTER_TABLE_SIZE];
00090 float *ftp = filterTable;
00091 for (int y = 0; y < FILTER_TABLE_SIZE; ++y) {
00092 float fy = ((float)y + .5f) * filter->yWidth / FILTER_TABLE_SIZE;
00093 for (int x = 0; x < FILTER_TABLE_SIZE; ++x) {
00094 float fx = ((float)x + .5f) * filter->xWidth / FILTER_TABLE_SIZE;
00095 *ftp++ = filter->Evaluate(fx, fy);
00096 }
00097 }
00098
00099
00100
00101
00102
00103
00104
00105 int arrsize = 8 * 1024;
00106 SampleArrptr = new ArrSample[arrsize];
00107 SampleArr2ptr = new ArrSample[arrsize];
00108
00109 curSampleArrId = 0;
00110 curSampleArr2Id = 0;
00111 maxSampleArrId = arrsize-1;
00112
00113 maxY = 0.f;
00114 warmupSamples = 0;
00115 warmupComplete = false;
00116 }
00117
00118 void FlexImageFilm::GetSampleExtent(int *xstart, int *xend,
00119 int *ystart, int *yend) const
00120 {
00121 *xstart = Floor2Int(xPixelStart + .5f - filter->xWidth);
00122 *xend = Floor2Int(xPixelStart + .5f + xPixelCount + filter->xWidth);
00123 *ystart = Floor2Int(yPixelStart + .5f - filter->yWidth);
00124 *yend = Floor2Int(yPixelStart + .5f + yPixelCount + filter->yWidth);
00125 }
00126
00127 int FlexImageFilm::RequestBuffer(BufferType type, BufferOutputConfig output,
00128 const string& filePostfix)
00129 {
00130 bufferConfigs.push_back(BufferConfig(type, output, filePostfix));
00131 return bufferConfigs.size() - 1;
00132 }
00133
00134 void FlexImageFilm::CreateBuffers()
00135 {
00136
00137 bufferGroups.push_back(BufferGroup());
00138 bufferGroups.back().CreateBuffers(bufferConfigs,xPixelCount,yPixelCount);
00139
00140
00141 if(writeResumeFlm && !restartResumeFlm) {
00142
00143
00144 string fname = filename+".flm";
00145 std::ifstream ifs(fname.c_str());
00146
00147 if(ifs.good()) {
00148
00149
00150 luxError(LUX_NOERROR, LUX_INFO, (std::string("Reading film status from file ")+fname).c_str());
00151
00152 UpdateFilm(NULL, ifs, 0, 0);
00153 }
00154
00155 ifs.close();
00156 }
00157 }
00158
00159 void FlexImageFilm::AddSample(float sX, float sY, const XYZColor &xyz, float alpha, int buf_id, int bufferGroup)
00160 {
00161 boost::recursive_mutex::scoped_lock lockSample(addSampleMutex);
00162
00163
00164 if (bufferGroups.empty()) {
00165 RequestBuffer(BUF_TYPE_PER_SCREEN, BUF_FRAMEBUFFER, "");
00166 CreateBuffers();
00167 }
00168
00169
00170
00171
00172 int arr_id = curSampleArrId;
00173 curSampleArrId++;
00174
00175
00176 SampleArrptr[arr_id].sX = sX;
00177 SampleArrptr[arr_id].sY = sY;
00178 SampleArrptr[arr_id].xyz = xyz;
00179 SampleArrptr[arr_id].alpha = alpha;
00180 SampleArrptr[arr_id].buf_id = buf_id;
00181 SampleArrptr[arr_id].bufferGroup = bufferGroup;
00182
00183
00184 if(curSampleArrId == maxSampleArrId) {
00185
00186 boost::recursive_mutex::scoped_lock lockArray(arrSampleMutex);
00187
00188
00189 ArrSample *tmpptr = SampleArrptr;
00190 SampleArrptr = SampleArr2ptr; SampleArr2ptr = tmpptr;
00191
00192
00193 curSampleArr2Id = curSampleArrId;
00194
00195 curSampleArrId = 0;
00196
00197
00198 boost::xtime currentTime;
00199 boost::xtime_get(¤tTime, boost::TIME_UTC);
00200 bool timeToWriteImage = (currentTime.sec - lastWriteImageTime.sec > writeInterval);
00201 if (timeToWriteImage)
00202 boost::xtime_get(&lastWriteImageTime, boost::TIME_UTC);
00203
00204
00205 lockSample.unlock();
00206
00207
00208 MergeSampleArray();
00209
00210
00211 lockArray.unlock();
00212
00213
00214 if (timeToWriteImage)
00215 WriteImage((ImageType)(IMAGE_FILEOUTPUT));
00216 }
00217 }
00218
00219 void FlexImageFilm::FlushSampleArray() {
00220 boost::recursive_mutex::scoped_lock lockSample(addSampleMutex);
00221
00222
00223 if (bufferGroups.empty()) {
00224 RequestBuffer(BUF_TYPE_PER_SCREEN, BUF_FRAMEBUFFER, "");
00225 CreateBuffers();
00226 }
00227
00228
00229 boost::recursive_mutex::scoped_lock lockArray(arrSampleMutex);
00230
00231
00232 ArrSample *tmpptr = SampleArrptr;
00233 SampleArrptr = SampleArr2ptr; SampleArr2ptr = tmpptr;
00234
00235
00236 curSampleArr2Id = curSampleArrId;
00237
00238 curSampleArrId = 0;
00239
00240
00241 lockSample.unlock();
00242
00243
00244 MergeSampleArray();
00245 }
00246
00247 void FlexImageFilm::MergeSampleArray() {
00248
00249
00250 if (curSampleArr2Id == 0) {
00251
00252 return;
00253 }
00254
00255 for(int sArrId = 0; sArrId < curSampleArr2Id - 1; sArrId++) {
00256 float sX = SampleArr2ptr[sArrId].sX;
00257 float sY = SampleArr2ptr[sArrId].sY;
00258 XYZColor xyz = SampleArr2ptr[sArrId].xyz;
00259 float alpha = SampleArr2ptr[sArrId].alpha;
00260 int buf_id = SampleArr2ptr[sArrId].buf_id;
00261 int bufferGroup = SampleArr2ptr[sArrId].bufferGroup;
00262
00263
00264 if (xyz.IsNaN() || xyz.y() < -1e-5f || isinf(xyz.y())) {
00265 if(debug_mode) {
00266 std::stringstream ss;
00267 ss << "Out of bound intensity in FlexImageFilm::AddSample: "
00268 << xyz.y() << ", sample discarded";
00269 luxError(LUX_LIMIT, LUX_WARNING, ss.str().c_str());
00270 }
00271 continue;
00272 }
00273
00274
00275 if(warmupComplete) {
00276 if(xyz.y() > maxY)
00277 continue;
00278 } else {
00279 if(debug_mode) {
00280 maxY = INFINITY;
00281 warmupComplete = true;
00282 }
00283 else if(warmupSamples < reject_warmup_samples) {
00284 if(xyz.y() > maxY)
00285 maxY = xyz.y();
00286 warmupSamples++;
00287 } else
00288 warmupComplete = true;
00289 }
00290
00291 BufferGroup ¤tGroup = bufferGroups[bufferGroup];
00292 Buffer *buffer = currentGroup.getBuffer(buf_id);
00293
00294
00295 float dImageX = sX - 0.5f;
00296 float dImageY = sY - 0.5f;
00297 int x0 = Ceil2Int (dImageX - filter->xWidth);
00298 int x1 = Floor2Int(dImageX + filter->xWidth);
00299 int y0 = Ceil2Int (dImageY - filter->yWidth);
00300 int y1 = Floor2Int(dImageY + filter->yWidth);
00301 x0 = max(x0, xPixelStart);
00302 x1 = min(x1, xPixelStart + xPixelCount - 1);
00303 y0 = max(y0, yPixelStart);
00304 y1 = min(y1, yPixelStart + yPixelCount - 1);
00305 if (x1 < x0 || y1 < y0) continue;
00306
00307
00308
00309 int ifx[32];
00310 for (int x = x0; x <= x1; ++x) {
00311 float fx = fabsf((x - dImageX) *
00312 filter->invXWidth * FILTER_TABLE_SIZE);
00313 ifx[x-x0] = min(Floor2Int(fx), FILTER_TABLE_SIZE-1);
00314 }
00315
00316 int ify[32];
00317 for (int y = y0; y <= y1; ++y) {
00318 float fy = fabsf((y - dImageY) *
00319 filter->invYWidth * FILTER_TABLE_SIZE);
00320 ify[y-y0] = min(Floor2Int(fy), FILTER_TABLE_SIZE-1);
00321 }
00322
00323 for (int y = y0; y <= y1; ++y) {
00324 for (int x = x0; x <= x1; ++x) {
00325
00326 int offset = ify[y-y0]*FILTER_TABLE_SIZE + ifx[x-x0];
00327 float filterWt = filterTable[offset];
00328
00329 buffer->Add(x - xPixelStart,y - yPixelStart,
00330 xyz, alpha, filterWt);
00331 }
00332 }
00333
00334 }
00335 }
00336
00337 void FlexImageFilm::WriteImage2(ImageType type, float* rgb, float* alpha, string postfix) {
00338
00339 if (type & IMAGE_FILEOUTPUT) {
00340
00341 if (writeUtmExr)
00342 WriteEXRImage(rgb, alpha, filename + postfix + "_untonemapped.exr");
00343
00344 if (writeUtmIgi)
00345 WriteIGIImage(rgb, alpha, filename + postfix + "_untonemapped.igi");
00346
00347
00348 if (writeResumeFlm)
00349 WriteResumeFilm(filename + ".flm");
00350 }
00351
00352
00353 if (((type & IMAGE_FRAMEBUFFER) && framebuffer) ||
00354 ((type & IMAGE_FILEOUTPUT) && (writeTmExr || writeTmIgi || writeTmTga))) {
00355
00356 ApplyImagingPipeline(rgb, xPixelCount, yPixelCount, NULL,
00357 0., 0., "reinhard",
00358 &toneParams, gamma, 0., 255);
00359
00360 if ((type & IMAGE_FRAMEBUFFER) && framebuffer) {
00361
00362 u_int nPix = xPixelCount * yPixelCount;
00363 for (u_int i = 0; i < nPix * 3; i++)
00364 framebuffer[i] = (unsigned char) rgb[i];
00365 }
00366
00367 if ((type & IMAGE_FILEOUTPUT) && (writeTmExr || writeTmIgi || writeTmTga)) {
00368
00369 if (writeTmTga)
00370 WriteTGAImage(rgb, alpha, filename + postfix + ".tga");
00371
00372 if (writeTmExr || writeTmIgi) {
00373
00374
00375
00376 int nPix = xResolution * yResolution;
00377 for (int i = 0; i < 3 * nPix; ++i) {
00378 rgb[i] /= 255;
00379 if (gamma != 1.f)
00380 rgb[i] = powf(rgb[i], gamma);
00381 }
00382
00383
00384 if (writeTmExr)
00385 WriteEXRImage(rgb, alpha, filename + postfix + ".exr");
00386
00387
00388 if (writeTmIgi)
00389 WriteIGIImage(rgb, alpha, filename + postfix + ".igi");
00390 }
00391 }
00392 }
00393 }
00394
00395 void FlexImageFilm::ScaleOutput(float *rgb, float *alpha, float *scale)
00396 {
00397 int x,y;
00398 int offset = 0;
00399 for (y = 0; y < yPixelCount; ++y)
00400 {
00401 for (x = 0; x < xPixelCount; ++x,++offset)
00402 {
00403 rgb[3*offset ] *= scale[offset];
00404 rgb[3*offset+1] *= scale[offset];
00405 rgb[3*offset+2] *= scale[offset];
00406 alpha[offset] *= scale[offset];
00407 }
00408 }
00409 }
00410 void FlexImageFilm::WriteImage(ImageType type)
00411 {
00412 boost::recursive_mutex::scoped_lock lock(imageMutex);
00413
00414
00415 FlushSampleArray();
00416
00417 int x,y,offset;
00418 int nPix = xPixelCount * yPixelCount;
00419 float *rgb0 = new float[3*nPix], *alpha0 = new float[nPix];
00420 float *rgb = new float[3*nPix], *alpha = new float[nPix];
00421 if (factor==NULL)
00422 {
00423 factor = new float[nPix];
00424 scene->camera->GetFlux2RadianceFactors(this,factor,xPixelCount,yPixelCount);
00425 }
00426 memset(rgb0,0,nPix*3*sizeof(*rgb0));
00427 memset(alpha0,0,nPix*sizeof(*alpha0));
00428
00429 for(u_int j=0;j<bufferGroups.size();++j)
00430 {
00431 for(u_int i=0;i<bufferConfigs.size();++i)
00432 {
00433 bufferGroups[j].buffers[i]->GetData(rgb, alpha);
00434 if (bufferConfigs[i].output & BUF_FRAMEBUFFER)
00435 {
00436 for (offset = 0, y = 0; y < yPixelCount; ++y)
00437 {
00438 for (x = 0; x < xPixelCount; ++x,++offset)
00439 {
00440 rgb0[3*offset ] += rgb[3*offset ];
00441 rgb0[3*offset+1] += rgb[3*offset+1];
00442 rgb0[3*offset+2] += rgb[3*offset+2];
00443 alpha0[offset] += alpha[offset];
00444 }
00445 }
00446 }
00447 if (bufferConfigs[i].output & BUF_STANDALONE)
00448 {
00449 if (!(bufferConfigs[i].output & BUF_RAWDATA) && scene->surfaceIntegrator->IsFluxBased())
00450 ScaleOutput(rgb,alpha,factor);
00451 WriteImage2(type, rgb, alpha, bufferConfigs[i].postfix);
00452 }
00453 }
00454
00455 if (scene->surfaceIntegrator->IsFluxBased())
00456 {
00457 ScaleOutput(rgb0,alpha0,factor);
00458 }
00459 WriteImage2(type, rgb0, alpha0, "");
00460 }
00461
00462 delete[] rgb;
00463 delete[] alpha;
00464 delete[] rgb0;
00465 delete[] alpha0;
00466 }
00467
00468
00469 void FlexImageFilm::createFrameBuffer()
00470 {
00471
00472 unsigned int nPix = xPixelCount * yPixelCount;
00473 framebuffer = new unsigned char[3*nPix];
00474
00475
00476 memset(framebuffer,0,sizeof(*framebuffer)*3*nPix);
00477 }
00478
00479 void FlexImageFilm::updateFrameBuffer()
00480 {
00481 if(!framebuffer)
00482 createFrameBuffer();
00483
00484 WriteImage(IMAGE_FRAMEBUFFER);
00485 }
00486
00487 unsigned char* FlexImageFilm::getFrameBuffer()
00488 {
00489 if(!framebuffer)
00490 createFrameBuffer();
00491
00492 return framebuffer;
00493 }
00494
00495 void FlexImageFilm::WriteResumeFilm(const string &filename)
00496 {
00497
00498 luxError(LUX_NOERROR, LUX_INFO, (std::string("Writing film status to file ") +
00499 filename).c_str());
00500
00501 std::ofstream filestr(filename.c_str());
00502 if(!filestr) {
00503 std::stringstream ss;
00504 ss << "Cannot open file '" << filename << "' for writing resume film";
00505 luxError(LUX_SYSTEM, LUX_SEVERE, ss.str().c_str());
00506
00507 return;
00508 }
00509
00510 TransmitFilm(filestr,0,0,false);
00511
00512 filestr.close();
00513 }
00514
00515 void FlexImageFilm::WriteTGAImage(float *rgb, float *alpha, const string &filename)
00516 {
00517
00518 luxError(LUX_NOERROR, LUX_INFO, (std::string("Writing Tonemapped TGA image to file ")+filename).c_str());
00519
00520
00521 FILE* tgaFile = fopen(filename.c_str(),"wb");
00522 if (!tgaFile) {
00523 std::stringstream ss;
00524 ss<< "Cannot open file '"<<filename<<"' for output";
00525 luxError(LUX_SYSTEM, LUX_SEVERE, ss.str().c_str());
00526 return;
00527 }
00528
00529
00530
00531 char header[18];
00532 memset(header, 0,sizeof(char)*18);
00533
00534 header[2] = 2;
00535 short xResShort = xResolution;
00536 header[13] = (char) (xResShort >> 8);
00537 header[12] = xResShort;
00538 short yResShort = yResolution;
00539 header[15] = (char) (yResShort >> 8);
00540 header[14] = yResShort;
00541 header[16] = 32;
00542
00543
00544 for (int i=0; i < 18; i++)
00545 fputc(header[i],tgaFile);
00546
00547
00548 for (int i=yPixelCount-1; i >= 0 ; i--) {
00549 for (int j=0; j < xPixelCount; j++) {
00550 fputc((int) rgb[(i*xPixelCount+j)*3+2], tgaFile);
00551 fputc((int) rgb[(i*xPixelCount+j)*3+1], tgaFile);
00552 fputc((int) rgb[(i*xPixelCount+j)*3+0], tgaFile);
00553
00554 fputc((int) 255.0, tgaFile);
00555
00556 }
00557 }
00558
00559 fclose(tgaFile);
00560
00561 }
00562
00563 void FlexImageFilm::WriteEXRImage(float *rgb, float *alpha, const string &filename)
00564 {
00565
00566 luxError(LUX_NOERROR, LUX_INFO, (std::string("Writing OpenEXR image to file ")+filename).c_str());
00567 WriteRGBAImageFloat(filename, rgb, alpha,
00568 xPixelCount, yPixelCount,
00569 xResolution, yResolution,
00570 xPixelStart, yPixelStart);
00571 }
00572
00573 void FlexImageFilm::WriteIGIImage(float *rgb, float *alpha, const string &filename)
00574 {
00575
00576 luxError(LUX_NOERROR, LUX_INFO, (std::string("Writing IGI image to file ")+filename).c_str());
00577 WriteIgiImage(filename, rgb, alpha,
00578 xPixelCount, yPixelCount,
00579 xResolution, yResolution,
00580 xPixelStart, yPixelStart);
00581 }
00582
00583
00584
00585 bool IsLittleEndian() {
00586 union ShortBytes {
00587 short shortValue;
00588 unsigned char bytes[2];
00589 };
00590
00591 ShortBytes shortTest;
00592 shortTest.shortValue = 1;
00593
00594 return (shortTest.bytes[0] == 1);
00595 }
00596
00597 void writeLittleEndianFloat(bool isLittleEndian, std::stringstream &os, float value) {
00598 if(isLittleEndian)
00599 os.write((char *)&value, sizeof(float));
00600 else {
00601 union FloatBytes {
00602 float floatValue;
00603 unsigned char bytes[4];
00604 };
00605
00606 FloatBytes f;
00607 f.floatValue = value;
00608
00609 for(unsigned int i = 0; i < sizeof(float); i++)
00610 os.write((char *)&f.bytes[sizeof(float) - i -1], 1);
00611 }
00612 }
00613
00614 void readLittleEndianFloat(bool isLittleEndian, filtering_stream<input> &in, float *value) {
00615 if(isLittleEndian)
00616 in.read((char *)value, sizeof(float));
00617 else {
00618 union FloatBytes {
00619 float floatValue;
00620 unsigned char bytes[4];
00621 };
00622
00623 FloatBytes f;
00624
00625 for(unsigned int i = 0; i < sizeof(float); i++)
00626 in.read((char *)&f.bytes[sizeof(float) - i -1], 1);
00627
00628 (*value) = f.floatValue;
00629 }
00630 }
00631
00632 void FlexImageFilm::TransmitFilm(
00633 std::basic_ostream<char> &stream,
00634 int buf_id, int bufferGroup,
00635 bool clearGroup) {
00636 BlockedArray<Pixel> *pixelBuf;
00637 float numberOfSamples;
00638 {
00639
00640 boost::recursive_mutex::scoped_lock lock(addSampleMutex);
00641
00642 BufferGroup ¤tGroup = bufferGroups[buf_id];
00643 Buffer *buffer = currentGroup.getBuffer(bufferGroup);
00644
00645 pixelBuf = new BlockedArray<Pixel>(*buffer->pixels);
00646 numberOfSamples = currentGroup.numberOfSamples;
00647
00648 if(clearGroup) {
00649
00650 buffer->Clear();
00651 currentGroup.numberOfSamples = 0;
00652 }
00653 }
00654
00655 bool isLittleEndian = IsLittleEndian();
00656
00657 std::stringstream ss;
00658 ss << "Transfering " << (pixelBuf->uSize() * pixelBuf->uSize()) <<
00659 " pixels (" <<numberOfSamples << " samples, little endian " <<
00660 (isLittleEndian ? "true" : "false") << ")";
00661 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
00662
00663 std::stringstream os;
00664 writeLittleEndianFloat(isLittleEndian, os, numberOfSamples);
00665
00666 for (int y = 0; y < pixelBuf->vSize(); ++y) {
00667 for (int x = 0; x < pixelBuf->uSize(); ++x) {
00668 Pixel &pixel = (*pixelBuf)(x, y);
00669 writeLittleEndianFloat(isLittleEndian, os, pixel.L.c[0]);
00670 writeLittleEndianFloat(isLittleEndian, os, pixel.L.c[1]);
00671 writeLittleEndianFloat(isLittleEndian, os, pixel.L.c[2]);
00672 writeLittleEndianFloat(isLittleEndian, os, pixel.alpha);
00673 writeLittleEndianFloat(isLittleEndian, os, pixel.weightSum);
00674 }
00675 }
00676 if(!os.good()) {
00677 luxError(LUX_SYSTEM, LUX_SEVERE, "Error preparing data for film resume file");
00678 delete pixelBuf;
00679 return;
00680 }
00681
00682 filtering_streambuf<input> in;
00683 in.push(gzip_compressor(9));
00684 in.push(os);
00685 std::streamsize size = boost::iostreams::copy(in, stream);
00686 if(!stream.good()) {
00687 luxError(LUX_SYSTEM, LUX_SEVERE, "Error writing film resume file");
00688 delete pixelBuf;
00689 return;
00690 }
00691
00692 ss.str("");
00693 ss << "Pixels transmition done (" << (size / 1024.0f) << " Kbytes sent)";
00694 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
00695
00696 delete pixelBuf;
00697 }
00698
00699 void FlexImageFilm::UpdateFilm(Scene *scene, std::basic_istream<char> &stream,
00700 int buf_id, int bufferGroup) {
00701 BlockedArray<Pixel> *pixelBuf;
00702 {
00703
00704 boost::recursive_mutex::scoped_lock lock(addSampleMutex);
00705
00706 BufferGroup ¤tGroup = bufferGroups[buf_id];
00707 Buffer *buffer = currentGroup.getBuffer(bufferGroup);
00708
00709 pixelBuf = new BlockedArray<Pixel>(buffer->xPixelCount, buffer->yPixelCount);
00710 }
00711
00712 filtering_stream<input> in;
00713 in.push(gzip_decompressor());
00714 in.push(stream);
00715
00716 bool isLittleEndian = IsLittleEndian();
00717
00718 float numberOfSamples;
00719 readLittleEndianFloat(isLittleEndian, in, &numberOfSamples);
00720 if (in.good()) {
00721 std::stringstream ss;
00722 ss << "Receiving " << numberOfSamples << " samples (little endian " <<
00723 (isLittleEndian ? "true" : "false") << ")";
00724 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
00725
00726 for (int y = 0; y < pixelBuf->vSize(); ++y) {
00727 for (int x = 0; x < pixelBuf->uSize(); ++x) {
00728 Pixel &pixel = (*pixelBuf)(x, y);
00729 readLittleEndianFloat(isLittleEndian, in, &pixel.L.c[0]);
00730 readLittleEndianFloat(isLittleEndian, in, &pixel.L.c[1]);
00731 readLittleEndianFloat(isLittleEndian, in, &pixel.L.c[2]);
00732 readLittleEndianFloat(isLittleEndian, in, &pixel.alpha);
00733 readLittleEndianFloat(isLittleEndian, in, &pixel.weightSum);
00734 }
00735 }
00736
00737
00738 if (in.good()) {
00739
00740 boost::recursive_mutex::scoped_lock lock(addSampleMutex);
00741
00742 BufferGroup ¤tGroup = bufferGroups[buf_id];
00743 Buffer *buffer = currentGroup.getBuffer(bufferGroup);
00744
00745 for (int y = 0; y < buffer->yPixelCount; ++y) {
00746 for (int x = 0; x < buffer->xPixelCount; ++x) {
00747 Pixel &pixel = (*pixelBuf)(x, y);
00748 Pixel &pixelResult = (*buffer->pixels)(x, y);
00749
00750 pixelResult.L.c[0] += pixel.L.c[0];
00751 pixelResult.L.c[1] += pixel.L.c[1];
00752 pixelResult.L.c[2] += pixel.L.c[2];
00753 pixelResult.alpha += pixel.alpha;
00754 pixelResult.weightSum += pixel.weightSum;
00755 }
00756 }
00757
00758 currentGroup.numberOfSamples += numberOfSamples;
00759
00760 if(scene != NULL)
00761 scene->numberOfSamplesFromNetwork += numberOfSamples;
00762 } else {
00763 luxError(LUX_SYSTEM, LUX_ERROR, "Error while reading samples");
00764 }
00765 } else {
00766 luxError(LUX_SYSTEM, LUX_ERROR, "Error while reading samples");
00767 }
00768
00769 delete pixelBuf;
00770 }
00771
00772
00773 Film* FlexImageFilm::CreateFilm(const ParamSet ¶ms, Filter *filter)
00774 {
00775
00776 bool premultiplyAlpha = params.FindOneBool("premultiplyalpha", true);
00777
00778 int xres = params.FindOneInt("xresolution", 800);
00779 int yres = params.FindOneInt("yresolution", 600);
00780
00781 float crop[4] = { 0, 1, 0, 1 };
00782 int cwi;
00783 const float *cr = params.FindFloat("cropwindow", &cwi);
00784 if (cr && cwi == 4) {
00785 crop[0] = Clamp(min(cr[0], cr[1]), 0.f, 1.f);
00786 crop[1] = Clamp(max(cr[0], cr[1]), 0.f, 1.f);
00787 crop[2] = Clamp(min(cr[2], cr[3]), 0.f, 1.f);
00788 crop[3] = Clamp(max(cr[2], cr[3]), 0.f, 1.f);
00789 }
00790
00791
00792 bool w_tonemapped_EXR = params.FindOneBool("write_tonemapped_exr", true);
00793 bool w_untonemapped_EXR = params.FindOneBool("write_untonemapped_exr", false);
00794 bool w_tonemapped_IGI = params.FindOneBool("write_tonemapped_igi", false);
00795 bool w_untonemapped_IGI = params.FindOneBool("write_untonemapped_igi", false);
00796 bool w_tonemapped_TGA = params.FindOneBool("write_tonemapped_tga", false);
00797
00798 bool w_resume_FLM = params.FindOneBool("write_resume_flm", false);
00799 bool restart_resume_FLM = params.FindOneBool("restart_resume_flm", false);
00800
00801
00802 string filename = params.FindOneString("filename", "luxout");
00803
00804
00805 int writeInterval = params.FindOneInt("writeinterval", 60);
00806 int displayInterval = params.FindOneInt("displayinterval", 12);
00807
00808
00809 float reinhard_prescale = params.FindOneFloat("reinhard_prescale", 1.0f);
00810 float reinhard_postscale = params.FindOneFloat("reinhard_postscale", 1.0f);
00811 float reinhard_burn = params.FindOneFloat("reinhard_burn", 6.0f);
00812
00813 float gamma = params.FindOneFloat("gamma", 2.2f);
00814
00815
00816 int reject_warmup = params.FindOneInt("reject_warmup", 3);
00817
00818
00819 bool debug_mode = params.FindOneBool("debug", false);
00820
00821 int haltspp = params.FindOneInt("haltspp", -1);
00822
00823 return new FlexImageFilm(xres, yres, filter, crop,
00824 filename, premultiplyAlpha, writeInterval, displayInterval,
00825 w_tonemapped_EXR, w_untonemapped_EXR, w_tonemapped_IGI, w_untonemapped_IGI, w_tonemapped_TGA, w_resume_FLM, restart_resume_FLM,
00826 haltspp, reinhard_prescale, reinhard_postscale, reinhard_burn, gamma, reject_warmup, debug_mode);
00827 }