00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "highcontrast.h"
00025 #include "stats.h"
00026 #include "dynload.h"
00027
00028 using namespace lux;
00029
00030
00031 void HighContrastOp::Map(vector<XYZColor> &xyz, int xRes, int yRes,
00032 float maxDisplayY) const {
00033 const int numPixels = xRes * yRes;
00034 float *lum = new float[numPixels];
00035
00036 float minY = INFINITY, maxY = 0.f;
00037 for (int i = 0; i < numPixels; ++i) {
00038 lum[i] = xyz[i].Y() * 683.f;
00039 minY = min(minY, lum[i]);
00040 maxY = max(maxY, lum[i]);
00041 }
00042 float CYmin = C(minY), CYmax = C(maxY);
00043
00044 MIPMapImpl<float, float> pyramid(MIPMAP_EWA, xRes, yRes, lum, 4.f,
00045 TEXTURE_CLAMP);
00046 delete[] lum;
00047
00048 ProgressReporter progress(xRes*yRes, "Tone Mapping");
00049 for (int y = 0; y < yRes; ++y) {
00050 float yc = (float(y) + .5f) / float(yRes);
00051 for (int x = 0; x < xRes; ++x) {
00052 float xc = (float(x) + .5f) / float(xRes);
00053
00054 float dwidth = 1.f / float(max(xRes, yRes));
00055 float maxWidth = 32.f / float(max(xRes, yRes));
00056 float width = dwidth, prevWidth = 0.f;
00057 float Yadapt;
00058 float prevlc = 0.f;
00059 const float maxLocalContrast = .5f;
00060 while (1) {
00061
00062 float b0 = pyramid.Lookup(xc, yc, width,
00063 0.f, 0.f, width);
00064 float b1 = pyramid.Lookup(xc, yc, 2.f * width,
00065 0.f, 0.f, 2.f * width);
00066 float lc = fabsf((b0 - b1) / b0);
00067
00068 if (lc > maxLocalContrast) {
00069 float t = (maxLocalContrast - prevlc) / (lc - prevlc);
00070 float w = Lerp(t, prevWidth, width);
00071 Yadapt = pyramid.Lookup(xc, yc, w,
00072 0.f, 0.f, w);
00073 break;
00074 }
00075
00076 prevlc = lc;
00077 prevWidth = width;
00078 width += dwidth;
00079 if (width >= maxWidth) {
00080 Yadapt = pyramid.Lookup(xc, yc, maxWidth,
00081 0.f, 0.f, maxWidth);
00082 break;
00083 }
00084 }
00085
00086 xyz[x + y*xRes] *= T(Yadapt, CYmin, CYmax) * 683.f /
00087 Yadapt;
00088 }
00089 progress.Update(xRes);
00090 }
00091 progress.Done();
00092 }
00093 ToneMap * HighContrastOp::CreateToneMap(const ParamSet &ps) {
00094 return new HighContrastOp;
00095 }
00096
00097 static DynamicLoader::RegisterToneMap<HighContrastOp> r("highcontrast");