Function Repository Resource:

CompileColorFunction

Source Notebook

Compile a color function for improved performance in colorizing images

Contributed by: Richard Hennigan (Wolfram Research)

ResourceFunction["CompileColorFunction"][f]

creates a CompiledFunction from the color function f.

Details and Options

ResourceFunction["CompileColorFunction"] generates a CompiledFunction object.
ResourceFunction["CompileColorFunction"] has the following options:
"ColorSamples"16number of data points to use in the compiled function
ColorSpace"RGB"what color space the output values should represent
CompilationOptionsAutomaticoptions for the complation process
CompilationTarget$CompilationTargetthe target runtime for code generation
ParallelizationTrueparallel controls for compiled function execution
RuntimeAttributes{Listable}evaluation attributes for the compiled function
RuntimeOptions"Speed"runtime options for the compiled function
In ResourceFunction["CompileColorFunction"][f], the function f should yield a valid color (as determined by ColorQ) when given real numbers between 0 and 1.
The compiled color function yields a vector of reals representing a color in the space specified by the ColorSpace option.

Examples

Basic Examples (3) 

Compile a color function:

In[1]:=
cf = ResourceFunction["CompileColorFunction"][
  RGBColor[Sin[#*Pi], #, 1 - #] &]
Out[1]=
In[2]:=
cf[0.123]
Out[2]=

See the resulting color:

In[3]:=
RGBColor[%]
Out[3]=

Compile a built-in color function from ColorData:

In[4]:=
cf = ResourceFunction["CompileColorFunction"][
  ColorData["TemperatureMap"]]
Out[4]=

Apply it to some data:

In[5]:=
cf[({
   {0, 1/8, 1/4},
   {3/8, 1/2, 5/8},
   {3/4, 7/8, 1}
  })]
Out[5]=

Get the resulting image:

In[6]:=
Image[%]
Out[6]=

Use a compiled color function in a plot:

In[7]:=
cf = ResourceFunction["CompileColorFunction"][
  ColorData["BlueGreenYellow"]]
Out[7]=
In[8]:=
DensityPlot[Sin[x y], {x, 0, 3}, {y, 0, 3}, ColorFunction -> (cf[#] &)]
Out[8]=

Scope (2) 

Generate colorized images from tables of data:

In[9]:=
cf = ResourceFunction["CompileColorFunction"][
  ColorData["SunsetColors"]]
Out[9]=
In[10]:=
data = Table[Sin[(x y)/400.]/2 + 1/2, {x, -200, 200}, {y, -200, 200}];
In[11]:=
Image[cf[data]]
Out[11]=

Create a fast color function from a slow one:

In[12]:=
slow[t_] := (Pause[.01]; ColorData["Rainbow"][t])
In[13]:=
cf = ResourceFunction["CompileColorFunction"][slow]
Out[13]=
In[14]:=
fast[t_] := cf[t]

Compare the performance:

In[15]:=
AbsoluteTiming[
 Plot3D[ Exp[1 - x^2 - y^2], {x, -2, 2}, {y, -2, 2}, ColorFunction -> Function[{x, y, z}, slow[z]], PlotRange -> All, Mesh -> None]]
Out[15]=
In[16]:=
AbsoluteTiming[
 Plot3D[ Exp[1 - x^2 - y^2], {x, -2, 2}, {y, -2, 2}, ColorFunction -> Function[{x, y, z}, fast[z]], PlotRange -> All, Mesh -> None]]
Out[16]=

Inspect timing details:

In[17]:=
ResourceFunction["EvaluationTiming"][
  Plot3D[Exp[1 - x^2 - y^2], {x, -2, 2}, {y, -2, 2}, ColorFunction -> Function[{x, y, z}, slow[z]], PlotRange -> All, Mesh -> None]]["Summary"]
Out[17]=
In[18]:=
ResourceFunction["NestedLookup"][
 Normal[%], {HoldForm[slow], "Overhead"}]
Out[18]=

The compiled version contributes an insignificant amount of overhead:

In[19]:=
ResourceFunction["EvaluationTiming"][
  Plot3D[Exp[1 - x^2 - y^2], {x, -2, 2}, {y, -2, 2}, ColorFunction -> Function[{x, y, z}, fast[z]], PlotRange -> All, Mesh -> None]]["Summary"]
Out[19]=
In[20]:=
ResourceFunction["NestedLookup"][
 Normal[%], {HoldForm[fast], "Overhead"}]
Out[20]=

Options (13) 

ColorSamples (2) 

Gradients that have a high amount of variance can lose some detail when compiled:

In[21]:=
f = ColorData["Rainbow"][Sin[25 #]/2 + 1/2] &
Out[21]=
In[22]:=
data = Transpose[
Table[
ConstantArray[x, 10], {x, 0, 1, 0.005}]];
In[23]:=
Image[Map[f, data, {2}]]
Out[23]=
In[24]:=
cf1 = ResourceFunction["CompileColorFunction"][f]
Out[24]=
In[25]:=
Image[cf1[data]]
Out[25]=

Use more initial color samples to increase the quality:

In[26]:=
cf2 = ResourceFunction["CompileColorFunction"][f, "ColorSamples" -> 256]
Out[26]=
In[27]:=
Image[cf2[data]]
Out[27]=

RuntimeAttributes (4) 

By default, CompileColorFunction will use Listable in the RuntimeAttributes:

In[28]:=
cf1 = ResourceFunction["CompileColorFunction"][
  ColorData["BlueGreenYellow"]]
Out[28]=

This allows the compiled function to be applied directly to an array of data:

In[29]:=
Image[cf1[RandomReal[1, {5, 5}]]]
Out[29]=
In[30]:=
cf1[{{0.25, 0.5}, {0.75, 0.25}}]
Out[30]=

If compiled without the Listable attribute, the function needs to be applied to individual values directly:

In[31]:=
cf2 = ResourceFunction["CompileColorFunction"][
  ColorData["BlueGreenYellow"], RuntimeAttributes -> {}]
Out[31]=
In[32]:=
cf2[{{0.25, 0.5}, {0.75, 0.25}}]
Out[32]=

It works if mapped:

In[33]:=
Image[Map[cf2, RandomReal[1, {5, 5}], {2}]]
Out[33]=

Parallelization (2) 

By default, Parallelization is set to True for CompileColorFunction:

In[34]:=
cf1 = ResourceFunction["CompileColorFunction"][
  ColorData["BrownCyanTones"]]
Out[34]=
In[35]:=
data = ImageData[
ImageResize[
ColorConvert[
ExampleData[{"TestImage", "Marruecos"}], "Grayscale"], 
Scaled[1/8]]];
In[36]:=
AbsoluteTiming[Image[cf1[data]]]
Out[36]=

Force the function to evaluate on a single thread:

In[37]:=
cf2 = ResourceFunction["CompileColorFunction"][
  ColorData["BrownCyanTones"], Parallelization -> False]
Out[37]=
In[38]:=
AbsoluteTiming[Image[cf2[data]]]
Out[38]=

CompilationTarget (2) 

If a C compiler is available on the current machine, additional performance may be obtained by setting CompilationTarget to "C":

In[39]:=
cf1 = ResourceFunction["CompileColorFunction"][Hue, CompilationTarget -> "C"]
Out[39]=
In[40]:=
data = Table[(1/10) (5 + y + Sin[x^2 + y^2]), {x, -4, 4, 0.05}, {
   y, -4, 4, 0.05}];
In[41]:=
RepeatedTiming[Image[cf1[data]]]
Out[41]=

Use the default value of "WVM":

In[42]:=
cf2 = ResourceFunction["CompileColorFunction"][Hue, CompilationTarget -> "WVM"]
Out[42]=
In[43]:=
RepeatedTiming[Image[cf2[data]]]
Out[43]=

ColorSpace (3) 

By default the values output by the compiled function will represent RGB values:

In[44]:=
cf1 = ResourceFunction["CompileColorFunction"][
  ColorData["StarryNightColors"]]
Out[44]=
In[45]:=
data = Table[(1/10) (5 + y + Sin[x^2 + y^2]), {x, -4, 4, 0.05}, {
   y, -4, 4, 0.05}];
In[46]:=
Image[cf1[data]]
Out[46]=

Specify a different color space:

In[47]:=
cf2 = ResourceFunction["CompileColorFunction"][
  ColorData["StarryNightColors"], ColorSpace -> "CMYK"]
Out[47]=
In[48]:=
colorized = cf2[data];

Now the ColorSpace needs to be specified for Image as well:

In[49]:=
Image[colorized]
Out[49]=
In[50]:=
Image[colorized, ColorSpace -> "CMYK"]
Out[50]=

Properties and Relations (2) 

Compiling a color function and applying directly to image data can improve performance over Colorize:

In[51]:=
data = Rescale[
Table[
With[{sum = 0.75 Sum[
Cos[(0.4 x) Cos[i (Pi/5.)] - (0.4 y) Sin[i (Pi/5.)]], {i, 5}]}, 
If[
OddQ[
Floor[sum]], 1 - Mod[sum, 1], 
Mod[sum, 1]]], {x, -256, 256}, {y, -256, 256}]];
img = Image[data]
Out[45]=
In[52]:=
cf = ResourceFunction["CompileColorFunction"][
  ColorData["SunsetColors"]]
Out[52]=
In[53]:=
RepeatedTiming@Image[cf[ImageData[img]]]
Out[53]=

Compare to using an uncompiled color function:

In[54]:=
RepeatedTiming@
 Colorize[img, ColorFunction -> ColorData["SunsetColors"]]
Out[54]=

Possible Issues (2) 

In CompileColorFunction[f], if the function f does not produce a smooth gradient when evaluated from 0 to 1, the compiled function can have low quality results:

In[55]:=
f = ColorData["DarkBands"]
Out[55]=
In[56]:=
data = Transpose[
Table[
ConstantArray[x, 10], {x, 0, 1, 0.005}]];
In[57]:=
Colorize[Image[data], ColorFunction -> f]
Out[57]=
In[58]:=
cf = ResourceFunction["CompileColorFunction"][f]
Out[58]=
In[59]:=
Image[cf[data]]
Out[59]=

The compiled function will be deterministic, even if the input function is not:

In[60]:=
f = RandomColor[] &
Out[60]=
In[61]:=
cf = ResourceFunction["CompileColorFunction"][f]
Out[61]=
In[62]:=
Image[cf[data]]
Out[62]=

The results won’t change when given the same input:

In[63]:=
Image[cf[data]]
Out[63]=

Compare to the original function:

In[64]:=
Colorize[Image[data], ColorFunction -> f]
Out[64]=

Neat Examples (1) 

Colorize data quickly for for interactive visualizations:

In[65]:=
Manipulate[
 Image[qcc[qc[grid, zoom, phase, order, mag, chop, wrap]]],
 {{order, 5}, 1, 11, 1, Sequence[
  ControlType -> SetterBar, ImageSize -> {153, 25}]},
 {phase, 0.0, 2.0 Pi, Sequence[
  ControlType -> Animator, ImageSize -> {153, 25}, AnimationRunning -> True, AppearanceElements -> {"ProgressSlider", "PlayPauseButton"}]},
 {{zoom, 0.25}, 0.05, 0.5, Sequence[
  ControlType -> Slider, ImageSize -> {153, 25}]},
 {{mag, 1.0}, 0.0, 2.0, Sequence[
  ControlType -> Slider, ImageSize -> {153, 25}]},
 {{chop, False}, {False, True}, ControlType -> Checkbox},
 {{wrap, True}, {False, True}, ControlType -> Checkbox},
 ControlPlacement -> Left,
 Initialization :> (
   $compilationTarget := ($compilationTarget = If[
Quiet[
TrueQ[
Not[Check[
Compile[{}, 1 + 1, CompilationTarget -> "C"], $tag, 
MessageName[CCompilerDriver`CreateLibrary, "nocomp"]] === $tag]]], "C", "WVM"]);
   qcc = ResourceFunction["CompileColorFunction"][
     ColorData["SunsetColors"], CompilationTarget -> $compilationTarget];
   xres = 350;
   yres = 350;
   grid = Array[{# - yres/2., #2 - xres/2.}& , {yres, xres}];
   qc = Compile[{{pt, 
Blank[Real], 1}, {scale, 
Blank[Real]}, {phase, 
Blank[Real]}, {order, 
Blank[Real]}, {mag, 
Blank[Real]}, {chop, 
Alternatives[True, False]}, {wrap, 
Alternatives[True, False]}}, 
Block[{x = Part[pt, 1], y = Part[pt, 2], sum = 0.}, Do[
AddTo[sum, 
Cos[phase + (scale x) Cos[i (Pi/order)] - (scale y) Sin[
           i (Pi/order)]]], {i, order}]; sum = mag sum; sum = If[wrap, 
If[
OddQ[
Floor[sum]], 1 - Mod[sum, 1], 
Mod[sum, 1]], 0.5 Tanh[sum] + 0.5]; If[
       chop, sum = 0.6 Floor[sum + 0.5] + 0.2]; sum], Parallelization -> True, RuntimeAttributes -> {Listable}, RuntimeOptions -> "Speed", CompilationTarget -> $compilationTarget];
   ),
 SynchronousInitialization -> False
 ]
Out[65]=

Requirements

Wolfram Language 11.3 (March 2018) or above

Version History

  • 1.0.0 – 27 March 2019

Related Resources

License Information