How can I sample from a gradient color scheme palette in segments of a fixed color distance? I.e, the next element appended to the generated list is a fixed distance from the most recently added color in the list. I have an initial color and would like to make regular samples from a color palette starting from this initial color.

  • $\begingroup$ Somewhat related to ResourceFunction[“SampleColors”] $\endgroup$ – user5601 Mar 19 at 18:48

We can make a little helper function:

SampleGradientFixedColorDistance[cf_, n_, m_ : 250] := 
 Module[{dists, vals, colors, if, max, newvals},
  vals = N@Subdivide[m];
  colors = cf /@ vals;
  dists = BlockMap[Apply[ColorDistance], colors, 2, 1];
  dists = Prepend[Accumulate[dists], 0];
  max = Max[dists];
  if = Interpolation[Transpose[{dists, vals}]];
  newvals = if /@ Subdivide[0, max, n - 1];
  cf /@ newvals

Which we can then call:

colors = SampleGradientFixedColorDistance[ColorData["Rainbow"], 20]

Compare it with linear sampling of the color scheme:

linearcolors = ColorData["Rainbow"] /@ Subdivide[20 - 1]

Now we can compare the distances between successive colors:

ListPlot[{BlockMap[Apply[ColorDistance], colors, 2, 1], 
  BlockMap[Apply[ColorDistance], linearcolors, 2, 1]}, 
 PlotRange -> All, PlotLegends -> {"Adjusted", "Linear"}, 
 Frame -> True]

enter image description here

It is not perfect, because color distances are not so nicely 'additive'. But it gives a reasonable improvement on the built-in.

| improve this answer | |
  • $\begingroup$ Any way of modifying this to start at an arbitrary intial color? I realize some colors may not exist inside the palette but then I could just use FindMatchingColor. $\endgroup$ – skyfire Mar 14 at 16:42
  • $\begingroup$ I'm not sure if that makes 'sense': to which point in the scheme would you go? the first? If your first choice is 'too far' one can not guarantee that 'n' colors is possible… $\endgroup$ – SHuisman Mar 14 at 17:26
  • $\begingroup$ So I have the color #c4d167 but would like to take samples of colors that are evenly spaced beginning at #c4d167. I don't want any sort of "wrapping around" the gradient if that is what you are asking. But I think it shoulud be possible to take fixed sample segments to the right and to the left beginning at #c4d167. $\endgroup$ – skyfire Mar 14 at 17:31
  • $\begingroup$ So starting at #c4d167 then move to the first color of the gradient, then continue taking steps of the same size in the gradient? $\endgroup$ – SHuisman Mar 14 at 17:40
  • $\begingroup$ Result would look like colorset = {..., c - Δd, c, c + Δd,...} where c = #c4d167 and d is the fixed color distance. $\endgroup$ – skyfire Mar 14 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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