compute optimal colors by ray tracing


Consider a colorSpec object x with type equal to responsivity.material. The set of all possible material reflectance functions (or transmittance functions) is convex, closed, and bounded (in any reasonable function space), and this implies that the set of all possible output responses from x is also convex, closed, and bounded. The latter set is called the object-color solid or Rösch Farbkörper for x. A color on the boundary of the object-color solid is called an optimal color. The special points W (the response to the perfect reflecting diffuser) and 0 are on the boundary of this set. The interior of the line segment of neutrals joining 0 to W is in the interior of the object-color solid. It is natural to parameterize this segment from 0 to 1 (from 0 to W).

A ray r that is based at a point on the interior of the neutral line segment must intersect the boundary of the object-color solid in a unique optimal color. The purpose of the function probeOptimalColors() is to compute that intersection point.

The function only works as stated if:

  1. the number of spectra in x is 3 (e.g. RGB or XYZ)

  2. the chromaticity diagram of x is convex and well-ordered (no reversals)

The 1st condition makes the situation simple enough to deal with. The 2nd condition implies that a reflectance function is optimal iff it takes the values 0 or 1, and has 0, 1, or 2 transitions; see Logvinenko or West for the proof of this. The proof in Schrödinger is flawed. This 2-transition condition also simplifies the situation. As an example, the CIE chromaticity diagrams (both 1931 and 1964) are convex. For counter-examples see the References. If a color defined by a reflectance function with 0, 1, or 2 transitions is called a Schrödinger color then it would be accurate to say that probeOptimalColors() computes Schrödinger object colors.


## S3 method for class 'colorSpec'
probeOptimalColors( x, gray, direction, tol=1.e-6, aux=FALSE )



a colorSpec object with type equal to responsivity.material and 3 spectra


vector of numbers in the open interval (0,1) that define neutral grays on the line segment from black to white; this neutral gray point is the basepoint of a probe ray


a vector of 3 numbers, or a matrix with 3 columns, that define 1 or more directions for the probe rays. A vector of 3 numbers is changed to a matrix with 1 row.


error tolerance for the intersection of probe and object-color boundary


a logical that specifies whether to return extra performance data; see Details


Each gray level and each direction defines a ray. So the total number of rays traced is length(gray) * ncol(direction). The intersection problem is reduced to a 2-dimension root finding problem which is solved using Newton's Method. The initial estimate is found by precomputing a fine quadrilateral mesh over the optimal colors.
The responsivity functions may be negative, but may not all simultaneously vanish at any wavelength. In that case the mapping from the ω and δ sphere to the output response space is not injective.


probeOptimalColors returns a data.frame with a row for each traced ray. There are length(gray) * ncol(direction) rays. The columns in the output are:


the graylevel defining the basepoint of the ray. basepoint = gray*W


the direction of the ray


computed scalar so that basepoint + s*direction is optimal


the optimal color on the boundary; optimal = basepoint + s*direction


lambda.1 and lambda.2 at the 2 transitions, in nm. lambda.1 < lambda.2 => bandpass, and lambda.1 > lambda.2 => bandstop.


delta and omega - the Logvinenko parameters (δ,ω) for optimal colors, plus lambda in nm. ω is the reparameterization of λ ; see References

And if aux is TRUE, these auxiliary columns related to performance:


time to find initial estimate point on boundary, in seconds


number of interations of Newton's Method to find the ray intersection


total # of backtracks in "damped" Newton's method


time spent in Newton iterations, in seconds


root-finding error, in coordinates of the optimal color. Always less than argument tol

If an individual ray could not be traced (see Known Issues), the row contains NA in appropriate columns.
In case of global error, the function returns NULL.

Known Issues

The optimal color boundary is not differentiable at 0 and W. There may be numerical iteration failures near these 2 points.


Logvinenko, A. D. An object-color space. Journal of Vision. 9(11):5, 1-23, (2009). doi:10.1167/9.11.5.

Schrödinger, E. (1920). Theorie der Pigmente von grösster Leuchtkraft. Annalen der Physik, 62, 603-622.

West, G. and M. H. Brill. Conditions under which Schrödinger object colors are optimal. Journal of the Optical Society of America. 73. pp. 1223-1225. 1983.

See Also

type, vignette optimals

Want to suggest features or report bugs for Use the GitHub issue tracker. Vote for new features on Trello.

comments powered by Disqus