12
$\begingroup$

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} *)

Mathematica graphics

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).

Thank you for your help.

$\endgroup$
3
  • $\begingroup$ 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. $\endgroup$
    – Mr.Wizard
    Mar 16, 2013 at 15:38
  • $\begingroup$ I finally remembered why I thought Raster was faster: this comment by Vitaliy Kaurov. $\endgroup$
    – Mr.Wizard
    Mar 16, 2013 at 16:04
  • 2
    $\begingroup$ 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. $\endgroup$
    – user484
    Jan 16, 2015 at 17:05

2 Answers 2

15
$\begingroup$

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 // Developer`ToPackedArray;
    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]

Mathematica graphics

Mathematica graphics

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}

enter image description here

Needs["GeneralUtilities`"]

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

enter image description here

$\endgroup$
16
  • $\begingroup$ Is it fair to say it is still significantly slower than Image? $\endgroup$
    – chris
    Mar 16, 2013 at 16:49
  • $\begingroup$ @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. $\endgroup$
    – Mr.Wizard
    Mar 16, 2013 at 16:52
  • $\begingroup$ @chris I upgraded my function and it is now about 40 times faster than ArrayPlot. Please take a look. $\endgroup$
    – Mr.Wizard
    Mar 16, 2013 at 17:15
  • $\begingroup$ That's a significant improvement indeed. $\endgroup$
    – chris
    Mar 16, 2013 at 17:21
  • $\begingroup$ 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. $\endgroup$
    – halirutan
    Mar 16, 2013 at 17:47
1
$\begingroup$

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"]]

Mathematica graphics


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.

$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.