# Using a given colour table with Image?

Context

I would like to represent large images with a given colour table.

Now, if I use Image

dat = RandomReal[{0, 1}, {1024, 1024}];
dat // Image; // Timing

(* ==> {0.000027, Null} *)


its fast, but in grayscales; on the other hand if I use, say MatrixPlot

dat // MatrixPlot[#, ColorFunction -> "Temperature"] &
dat // MatrixPlot[#, ColorFunction -> "Temperature"] &; // Timing

(* ==> {1.5748, Null} *)


its in colour, but its slow.

Question

Is there a method to get the best of both worlds? (i.e. Speed and chosen colour table).

• I updated my answer. I wonder if there is a faster method available. I think perhaps a compiled function working on the image data directly would do it. – Mr.Wizard Mar 16 '13 at 15:38
• I finally remembered why I thought Raster was faster: this comment by Vitaliy Kaurov. – Mr.Wizard Mar 16 '13 at 16:04
• For completeness, I'll point out that the built-in function for applying a colour map to a grayscale image is Colorize. This is about twice as fast as ArrayPlot, though of course not nearly as fast as Mr.Wizard's renderImage. – user484 Jan 16 '15 at 17:05

I think I finally succeeded in creating something faster.

Edit: now ~40X faster than ArrayPlot.

renderImage[
array_?MatrixQ,
cf_,
q_Integer: 2048,
opts : OptionsPattern[Image]
] :=
Module[{tbl},
tbl = List @@@ Array[cf, q, {0, 1}] // N // DeveloperToPackedArray;
Image[tbl[[# + 1]] & /@ Round[(q - 1) array], opts]
]


A test of function:

dat = Map[Mean, ImageData[Import["ExampleData/lena.tif"]], {2}];

ArrayPlot[dat, ColorFunction -> "Rainbow"]

renderImage[dat, ColorData["Rainbow"], ImageSize -> 300]


A test of speed:

big = RandomReal[1, {1500, 1500}];

ArrayPlot[big, ColorFunction -> "Rainbow"] // Timing // First

renderImage[big, ColorData["Rainbow"], ImageSize -> 300] // Timing // First


2.325

0.0624

And this time that's correct timing data.

### Update

I have added a parameter q to control the number of quantization steps used. It arbitrarily defaults to 2048 which appears to be visually sufficient for most schemes and images. Examples of effect on quality and timing:

renderImage[dat, ColorData["Rainbow"], #, ImageSize -> 300] & /@ {7, 10000}


Needs["GeneralUtilities"]

BenchmarkPlot[
{renderImage[big, ColorData["Rainbow"], #] &},
Identity,
5^Range[9]
]


• Is it fair to say it is still significantly slower than Image? – chris Mar 16 '13 at 16:49
• @chris Certainly, but anything is likely to be as the color look-up has to to take some amount of time. Still I believe a compiled function would be faster but that's not my strength so I'll leave it for someone else. This at least lays the foundation. – Mr.Wizard Mar 16 '13 at 16:52
• @chris I upgraded my function and it is now about 40 times faster than ArrayPlot. Please take a look. – Mr.Wizard Mar 16 '13 at 17:15
• That's a significant improvement indeed. – chris Mar 16 '13 at 17:21
• The thing is: by creating a lookup table for the colors you do a quantization which is not done by ArrayPlot. Although, the visual outcome may look the same, we compare two different things here. – halirutan Mar 16 '13 at 17:47

This answer was posted in error. Nevertheless I think the information below is helpful.

I believe the fastest general method is Raster, like this:

Graphics[Raster[RandomReal[1, {10, 20}], ColorFunction -> "Rainbow"]]


Actually, this isn't any faster than MatrixPlot, it's just different. With MatrixPlot the time is spent when the graphic is created, and with Raster it is spent when it is displayed:

Timing[g1 = MatrixPlot[dat, ColorFunction -> "Temperature"];]
Timing[g2 = Graphics[Raster[dat, ColorFunction -> "Temperature"]];]

{0.639, Null}

{0., Null}


To see the rendering time set:

SetOptions[\$FrontEndSession, EvaluationCompletionAction->"ShowTiming"]


Then:

g1

g2


and you will see that g1 displays immediately, whereas g2 takes about as long to render as it did to create g1`.