Saturday, May 26, 2012

Image Processing

Here are a few examples of a few of the post-processing features I've built into in Photorealizer. The differences are somewhat subtle in some of these images. I could have pumped up the filter settings more in some of images here to show the effects better, but I was mainly creating them for my own testing. To see the differences as clearly as possible, you'll probably want to click them to open them in Lightbox then switch back and forth between them. The material I used here is a slightly rough green glass using the microfacet model for transmission through rough surfaces. I limited the trace depth, so parts of the Lucy model aren't as full and saturated as they would be with higher quality settings, but the images are still useful for illustration and comparison.

Even newer transfer curve, plus lower exposure (added 1/17/2013).

Even newer transfer curve (added 1/17/2013). This curve does a better job of increasing the contrast of the perceptual midtones, and better maintains the overall luminosity of the image.

My new sinusoidal contrast curve, maxed out.

New contrast curve, plus bloom. Bloom can make the blown out brights look brighter, and can make renders look a little more realistic, however the bloom is probably too extreme in this case, and there's room for improvment in other ways as well.

My new sinusoidal contrast curve, with a wet/dry mix setting that mixes the curve with a straight line. Unprocessed linear images can look too flat when displayed on a computer screen, exactly like an unprocessed raw image from a digital camera.

My old contrast curve with circular roll-off. Darkens darks, lightens lights, and slightly increases contrast.

Just gamma corrected. Display-linear.

Not gamma corrected.

My old contrast curve.

No contrast curve (just gamma corrected).

Graph of my old contrast curve (rendered in Photorealizer, overriding ray tracing).


  1. Great blog! When in the pipeline do you apply your contrast/transfer curves, is it instead of gamma or alongside with it? I'd like to implement something like this in my renderer too, as I'm suffering from the usual gamma/sRGB color flatness, so any insight you can share would be useful.

    1. Hey, thanks.

      All of the rendering is done with scene-linear, high dynamic range, floating-point numbers, and the pixel values are stored that way in the renderer. Then, when I want to generate an image for a standard 8-bit display, that's when I apply the contrast/transfer curves. This happens in addition to gamma correction. It would also be possible to combine both gamma and contrast into a single transfer curve, but I think it's better to keep them separate, so that one can be modified independently of the other. I apply these curves (and sometimes other filters) to the floating-point pixel values before converting to 8-bit and doing dithering. This all happens long after anti-aliasing.

      I just updated the post with two new images that use my newest transfer curve. I now apply the contrast curve after gamma correction. Since my transfer curve is S-shaped and rotationally symmetric around 0.5, this has the effect of increasing the contrast most in the perceptual midtones (which also happen to be in the middle of the gamma/sRGB curve), and it preserves the overall luminosity of the image. The transfer curve doesn't modify input values of 0.5 at all, but the slope is steepest around 0.5.

      I came up with my transfer curves after researching film response curves and the image processing that goes on when digital cameras convert raw sensor data to low dynamic range images. I didn't find exact formulas, so I just made up my own curves.

      You can find some information about S-shaped transfer curves (plus lots more) in a great paper called Cinematic Color which you can find at

      Hopefully that helps. Sorry if any of it isn't clear—I wrote this reply pretty fast so that I could include as much information as possible.

  2. Thanks a lot for taking the time to reply. Sounds like we do pretty much the same thing, I do Spectrum -> XYZ (this is how the values are stored in the film buffer) -> RGB (HDR) -> Tonemap -> sRGB (the "correct" way, not just the gamma curve) -> 8bit -> dither. As your blog post mentioned "sinusoidal" I already started experimenting with a sinusoidal curve ("squeezing" a sine curve into the 0->1 range), but I interpolated it (linearly) with the sRGB curve (probably a bit like your "dry"/"wet" setting), in essence doing both contrast and gamma in one go. The results were nice in that the colors were more vivid and saturated, but as you pointed out the luminance dropped more and more when shifting more toward the sinusoidal curve. I'll try your method (gamma first, then contrast) and see what I get from it. Nice images btw (with the new curve), and thanks for turning my attention to these color issues, I was giving up hope on ever getting vivid colors out of my renderer. I'll hopefully get a much overdue blog up and running during the weekend, I'll post my results there. (I'm having problems posting with my google account, hence the anonymous posting).

    // Mario