00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef LUX_FLEXIMAGE_H
00024 #define LUX_FLEXIMAGE_H
00025
00026 #include "lux.h"
00027 #include "film.h"
00028 #include "color.h"
00029 #include "paramset.h"
00030 #include "tonemap.h"
00031 #include "sampling.h"
00032 #include <boost/thread/xtime.hpp>
00033 #include <boost/thread/recursive_mutex.hpp>
00034
00035 namespace lux {
00036
00037 class BufferConfig {
00038 public:
00039 BufferConfig(BufferType t, BufferOutputConfig o, const string& s) :
00040 type(t), output(o), postfix(s) { }
00041 BufferType type;
00042 BufferOutputConfig output;
00043 string postfix;
00044 };
00045
00046 struct Pixel {
00047
00048 friend class boost::serialization::access;
00049
00050 template<class Archive> void serialize(Archive & ar, const unsigned int version) {
00051 ar & L;
00052 ar & alpha;
00053 ar & weightSum;
00054 }
00055
00056 Pixel(): L(0.f), alpha(0.f), weightSum(0.f) { }
00057 XYZColor L;
00058 float alpha, weightSum;
00059 };
00060
00061 class Buffer {
00062 public:
00063 Buffer(int x, int y) {
00064 xPixelCount = x;
00065 yPixelCount = y;
00066 pixels = new BlockedArray<Pixel>(x, y);
00067 }
00068
00069 virtual ~Buffer() {
00070 delete pixels;
00071 }
00072
00073 void Add(int x, int y, XYZColor L, float alpha, float wt) {
00074 Pixel &pixel = (*pixels)(x, y);
00075 pixel.L.AddWeighted(wt, L);
00076 pixel.alpha += alpha * wt;
00077 pixel.weightSum += wt;
00078 }
00079
00080 void Clear() {
00081 for (int y = 0, offset = 0; y < yPixelCount; ++y) {
00082 for (int x = 0; x < xPixelCount; ++x, ++offset) {
00083 Pixel &pixel = (*pixels)(x, y);
00084 pixel.L.c[0] = 0.0f;
00085 pixel.L.c[1] = 0.0f;
00086 pixel.L.c[2] = 0.0f;
00087 pixel.alpha = 0.0f;
00088 pixel.weightSum = 0.0f;
00089 }
00090 }
00091 }
00092
00093 virtual void GetData(float *rgb, float *alpha) = 0;
00094 bool isFramebuffer;
00095 int xPixelCount, yPixelCount;
00096 float scaleFactor;
00097 BlockedArray<Pixel> *pixels;
00098 };
00099
00100
00101 class RawBuffer : public Buffer {
00102 public:
00103 RawBuffer(int x, int y) : Buffer(x, y) { }
00104
00105 ~RawBuffer() { }
00106
00107 void GetData(float *rgb, float *alpha) {
00108 for (int y = 0, offset = 0; y < yPixelCount; ++y) {
00109 for (int x = 0; x < xPixelCount; ++x, ++offset) {
00110 Pixel &pixel = (*pixels)(x, y);
00111 rgb[3*offset ] = pixel.L.c[0];
00112 rgb[3*offset+1] = pixel.L.c[1];
00113 rgb[3*offset+2] = pixel.L.c[2];
00114 alpha[offset] = pixel.alpha;
00115 }
00116 }
00117 }
00118 };
00119
00120
00121 class PerPixelNormalizedBuffer : public Buffer {
00122 public:
00123 PerPixelNormalizedBuffer(int x, int y) : Buffer(x, y) { }
00124
00125 ~PerPixelNormalizedBuffer() { }
00126
00127 void GetData(float *rgb, float *alpha) {
00128 for (int y = 0, offset = 0; y < yPixelCount; ++y) {
00129 for (int x = 0; x < xPixelCount; ++x, ++offset) {
00130 Pixel &pixel = (*pixels)(x, y);
00131 if (pixel.weightSum == 0.f) {
00132 alpha[offset] = 0.f;
00133 rgb[3*offset ] = 0.f;
00134 rgb[3*offset+1] = 0.f;
00135 rgb[3*offset+2] = 0.f;
00136 } else {
00137 float inv = 1.f / pixel.weightSum;
00138
00139 pixel.L.ToRGB(rgb + 3 * offset);
00140 rgb[3*offset ] *= inv;
00141 rgb[3*offset+1] *= inv;
00142 rgb[3*offset+2] *= inv;
00143 alpha[offset] = pixel.alpha;
00144 }
00145 }
00146 }
00147 }
00148 };
00149
00150
00151 class PerScreenNormalizedBuffer : public Buffer {
00152 public:
00153 PerScreenNormalizedBuffer(int x, int y, const float *samples) :
00154 Buffer(x, y), numberOfSamples_(samples) { }
00155
00156 ~PerScreenNormalizedBuffer() { }
00157
00158 void GetData(float *rgb, float *alpha) {
00159 float inv = xPixelCount * yPixelCount / *numberOfSamples_;
00160 for (int y = 0, offset = 0; y < yPixelCount; ++y) {
00161 for (int x = 0; x < xPixelCount; ++x, ++offset) {
00162 Pixel &pixel = (*pixels)(x, y);
00163
00164 pixel.L.ToRGB(rgb + 3 * offset);
00165 rgb[3*offset ] *= inv;
00166 rgb[3*offset+1] *= inv;
00167 rgb[3*offset+2] *= inv;
00168 alpha[offset] = pixel.alpha;
00169 }
00170 }
00171 }
00172 private:
00173 const float *numberOfSamples_;
00174 };
00175
00176
00177 class BufferGroup {
00178 public:
00179 BufferGroup() : numberOfSamples(0.f) { }
00180 ~BufferGroup() {
00181 for(vector<Buffer *>::iterator buffer = buffers.begin(); buffer != buffers.end(); ++buffer)
00182 delete *buffer;
00183 }
00184
00185 void CreateBuffers(const vector<BufferConfig> &configs, int x, int y) {
00186 for(vector<BufferConfig>::const_iterator config = configs.begin(); config != configs.end(); ++config) {
00187 switch ((*config).type) {
00188 case BUF_TYPE_PER_PIXEL:
00189 buffers.push_back(new PerPixelNormalizedBuffer(x, y));
00190 break;
00191 case BUF_TYPE_PER_SCREEN:
00192 buffers.push_back(new PerScreenNormalizedBuffer(x, y, &numberOfSamples));
00193 break;
00194 case BUF_TYPE_RAW:
00195 buffers.push_back(new RawBuffer(x, y));
00196 break;
00197 default:
00198 assert(0);
00199 }
00200 }
00201 }
00202
00203 Buffer *getBuffer(int index) {
00204 return buffers[index];
00205 }
00206 float numberOfSamples;
00207 vector<Buffer *> buffers;
00208 };
00209
00210
00211 class FlexImageFilm : public Film {
00212 public:
00213
00214 FlexImageFilm(int xres, int yres) :
00215 Film(xres, yres, 0), filter(NULL), filterTable(NULL),
00216 framebuffer(NULL), factor(NULL) { }
00217
00218 FlexImageFilm(int xres, int yres, Filter *filt, const float crop[4],
00219 const string &filename1, bool premult, int wI, int dI,
00220 bool w_tonemapped_EXR, bool w_untonemapped_EXR, bool w_tonemapped_IGI,
00221 bool w_untonemapped_IGI, bool w_tonemapped_TGA, bool w_resume_FLM, bool restart_resume_FLM,
00222 int haltspp, float reinhard_prescale, float reinhard_postscale,
00223 float reinhard_burn, float g, int reject_warmup, bool debugmode);
00224 ~FlexImageFilm() {
00225 delete[] framebuffer;
00226 delete[] factor;
00227 }
00228
00229 int RequestBuffer(BufferType type, BufferOutputConfig output, const string& filePostfix);
00230 void CreateBuffers();
00231
00232 void GetSampleExtent(int *xstart, int *xend, int *ystart, int *yend) const;
00233 void AddSample(float sX, float sY, const XYZColor &L, float alpha, int buf_id = 0, int bufferGroup = 0);
00234 void AddSampleCount(float count, int bufferGroup = 0) {
00235 if (!bufferGroups.empty()) {
00236 bufferGroups[bufferGroup].numberOfSamples += count;
00237
00238
00239 if ((haltSamplePerPixel > 0) &&
00240 (bufferGroups[bufferGroup].numberOfSamples * invSamplePerPass >=
00241 haltSamplePerPixel))
00242 enoughSamplePerPixel = true;
00243 }
00244 }
00245
00246 void WriteImage(ImageType type);
00247
00248
00249 void updateFrameBuffer();
00250 unsigned char* getFrameBuffer();
00251 void createFrameBuffer();
00252 float getldrDisplayInterval() {
00253 return displayInterval;
00254 }
00255
00256
00257 void TransmitFilm(std::basic_ostream<char> &stream,
00258 int buf_id = 0, int bufferGroup = 0, bool clearBuffer = true);
00259 void UpdateFilm(Scene *scene, std::basic_istream<char> &stream,
00260 int buf_id = 0, int bufferGroup = 0);
00261
00262 static Film *CreateFilm(const ParamSet ¶ms, Filter *filter);
00263
00264 private:
00265 void FlushSampleArray();
00266
00267 void MergeSampleArray();
00268
00269 void WriteImage2(ImageType type, float* rgb, float* alpha, string postfix);
00270 void WriteTGAImage(float *rgb, float *alpha, const string &filename);
00271 void WriteEXRImage(float *rgb, float *alpha, const string &filename);
00272 void WriteIGIImage(float *rgb, float *alpha, const string &filename);
00273 void WriteResumeFilm(const string &filename);
00274 void ScaleOutput(float *rgb, float *alpha, float *scale);
00275
00276
00277 Filter *filter;
00278 int writeInterval;
00279 int displayInterval;
00280 string filename;
00281 bool premultiplyAlpha, buffersInited;
00282 float cropWindow[4], *filterTable;
00283 int xPixelStart, yPixelStart, xPixelCount, yPixelCount;
00284 ParamSet toneParams;
00285 float gamma;
00286 float reject_warmup_samples;
00287 bool writeTmExr, writeUtmExr, writeTmIgi, writeUtmIgi, writeTmTga, writeResumeFlm, restartResumeFlm;
00288
00289 unsigned char *framebuffer;
00290
00291
00292 boost::xtime lastWriteImageTime;
00293
00294 bool debug_mode;
00295 float *factor;
00296
00297 std::vector<BufferConfig> bufferConfigs;
00298 std::vector<BufferGroup> bufferGroups;
00299
00300 mutable boost::recursive_mutex addSampleMutex;
00301
00302 float maxY;
00303 u_int warmupSamples;
00304 bool warmupComplete;
00305 ArrSample *SampleArrptr;
00306 ArrSample *SampleArr2ptr;
00307
00308
00309
00310 mutable boost::recursive_mutex arrSampleMutex;
00311 int curSampleArrId, curSampleArr2Id, maxSampleArrId;
00312
00313
00314 mutable boost::recursive_mutex imageMutex;
00315 };
00316
00317 }
00318
00319 #endif //LUX_FLEXIMAGE_H
00320