What you can do is, you mimic the behaviour of Blend
by creating a function that interpolates linearly between colours. What you change with your parameters are the values where the color transitions take place.
Let me give you a simplified example: I use 3 colours. In the compiled function, I only work with their {r,g,b}
values. As result, I want a compiled function which does the following:
- it takes a parameter
a
between 0 and 1 and a pixel value
between 0 and 1
- with 3 colours
c1
, c2
and c3
it will colorise the pixel: from a pixel value of 0 to a
it will be colorised with the transition c1
to c2
. If the pixel value
is greater than a
it will be colorised by blending c2 and c3.
- the compiled function should be able to work in parallel on all pixels of an image
Here is a sample implementation of a function that creates such a colorising compiled function for us:
createColorFunc[colors : {_, _, _}] :=
Function[{c1, c2, c3},
Compile[{{a, _Real, 0}, {value, _Real, 0}},
If[value < a,
c1 + ((-c1 + c2)*value)/a,
(c3*(a - value) + c2*(-1 + value))/(-1 + a)
], Parallelization -> True, RuntimeAttributes -> {Listable}
]
] @@ List @@@ (ColorConvert[#, "RGB"] & /@ colors)
To test is, we load the Lena image in grayscale an build a small Manipulate
:
With[{lena = ColorConvert[ExampleData[{"TestImage", "Lena"}], "Grayscale"]},
Manipulate[
func = createColorFunc[{c1, c2, c3}];
Image[func[a, ImageData[lena, "Real"]]],
{{a, .5}, 0, 1},
{c1, Black},
{c2, Gray},
{c3, White}
]
]

You task is now to extend this for more than 3 colours and one color transition position.