P3 Tonemapper Architecture Description

Harrison Ainsworth

ARTIFEX (ατ) HXA7241 (dοτ) ORG


Copyright (c) 2005, Harrison Ainsworth / HXA7241.



Develop a premium tone-mapper component available as source code, library and executable.

Implement Ward Larson's 1997 paper:

‘A Visibility Matching Tone Reproduction Operator for High Dynamic Range Scenes’
Ward Larson, Rushmeier, Piatko;


Tone mapping is a necessary stage of rendering, but it is usually an afterthought. A good component could fill a gap in the open-source rendering world. It can be well-separated and made reusable without architectural ramifications. It is quite small and simple, so do-able in a month or two.



Requirements are simple: there is only one use case, and a few supplementary features. The use case follows basic command-line tool form: read a file, process it, output a file. But this is augmented with an options file containing switches and metadata.

Use Case

(actor - user, or renderer)

  1. issue command, input command file
  2. input HDR image (XYZ, RGB (maybe with conversion)) (RGBE or OpenEXR)
  3. (maybe read output error file, then repeat from first step)
  4. receive RGB int (8 or 16 bit) image file (PNG or PPM)

Use Case Features


The primary division separates the user-interface application from the library. In the library the tonemapping specific algorithm is separated from more general graphics and utilities parts. In the application the image file formatting is separated.


reuse (and extend a little):

Package Dependencies



The main tonemap package classes fall into three groups: some specialised images, some image operators, and one overall workflow-context.

Components/Libraries Reused

image file format support:

Class Interfaces


  1. read commands
  2. read original image file
  3. make PerceptualMap object
  4. map original image to final image
    1. make foveal image
    2. apply human viewer limitations
      1. make veil image
      2. mix veil into foveal image
      3. mix veil into original image
      4. adjust original image for color sensitivity
      5. filter original image for acuity
    3. make ToneAdjustment
      1. make histogram
      2. adjust histogram
      3. make cumulative function from histogram
    4. map original image with ToneAdjustment
  5. write final image file


A simple, basic form eases portability, and the usage is simple, so: a command-line program is best. This can be a thin wrapper to control a dynamic-link/shared library. Maybe the image format readers could be externalised as plugins.


Just straightforward, portable C++.


Not decided yet... Something precise and numerical is desirable. There are some source and result images, using the same algorithm, at: http://www.anyhere.com/gward/hdrenc/pages/originals.html , and some calibrated images at: http://www.mpi-inf.mpg.de/resources/hdr/gallery.html

Technical Notes

  1. input original image

    • pixels: RGB float (maybe with color space)
  2. make image of foveal values

    • pixels: RGB float
    • (box/cheap) filter to 1degree/pixel size
    • pixelcount = 2 * tan( viewangle / 2 ) / 0.01745
  3. human viewer

    • make image of veil, from foveal image

      • pixels: RGB float
      • same resolution as foveal image
      • (color, not just luminance)
      • (slowest part - big convolution ...)
    • mix veil into foveal

    • mix veil into original

      • (with a bilinear interpolation)
    • adjust original image for color sensitivity

      • needs conversion to XYZ (to get foveal luminance)
    • filter original image for acuity

      • needs conversion to XYZ (to get foveal luminance)
      • variable blur - mipmap?
  4. make histogram, from foveal image

    • needs conversion to XYZ
    • elements: log10 of luminances
    • 100 bins
    • min = min val, clamped to min of 10^-4
    • max = max val
    • log10lum -> log10lum
    • (linearly interpolatable)
  5. adjust histogram

    • clamp counts, using iterative convergence
      • linear ceiling - ideal viewer
      • varying ceiling - human viewer
  6. map original image with histogram

  7. output final image

    • pixels: RGB int

command file:

(luminance is cd/m^2, remember?)



elaboration order

  1. image types
  2. color conversion
  3. tonemap
    1. PerceptualMap
    2. Foveal
    3. Veil
    4. ToneAdjustment
    5. AcuityFilter
    6. ColorAdjustment
  4. formatting

construction order

  1. basic skeleton app
  2. image types
  3. color conversion
  4. PerceptualMap
  5. Foveal
  6. Veil
  7. ToneAdjustment
  8. AcuityFilter
  9. ColorAdjustment
  10. basic formatters
  11. user application
  12. other formatters

next version prospectus