Palette to clut to application


I don’t have much experience with CLUTs but I have been thinking on whether it would be possible to generate one based on a limited palette and apply it in a natural way. E.g., I have the following arbitrary palette where the colors are in a particular order and some are more prominent than others:

Edit: sorry, I messed up the png as @samj pointed out.
Palette A

Palette B

Maybe include the cases where we disregard the prominence and / or order… I don’t know if this is practical but I see the utility of generating looks very quickly and easily based on palettes. Perhaps a tool already exists that I haven’t explored yet. Please direct me in the right direction. Thanks.

Some ideas could be found here: The part on interpolation.

Kovesi's functions

Here’s a related filter:
Perhaps some ideas can be taken from that (it generates a clut). There are simpler ways for your type of input though.

(Morgan Hardwood) #3

Generating a look based on that pallet sounds nice, and by not specifying exactly how a given image which you refer to as a pallet is supposed to translate into a CLUT, the implementation of that part was given creative freedom. I was curious what would happen if… so here are two approaches:

  1. Generate an identity HaldCLUT whose number of levels matches the color count of the pallet:
    convert hald:5 -depth 8 -colorspace sRGB hald5.png
    Create the pallet in a form which matches the CLUT levels:
    Then overlay the CLUT over the identity CLUT (I used “Color (LCH)” blending mode):
  2. Use G’MIC

The test image:

amsterdam.pef.pp3 (10.9 KB)

The “Color (LCH)” result:

The G’MIC result:


@garagecoder I am aware of your filter (#2). Is there a way to handle haldcluts in gmic?

@Morgan_Hardwood Thanks. I like the result of approach #1. It is much more dynamic than #2. Open questions invite creative solutions :slight_smile:.

(samj) #5


Thanks to afre and Morgan_Hardwood for their ideas :o)
I tried to make a color transfer using gradients obtained from the palette.
I only used G’MIC.

Edit : I copied afre’s palette and the transparent area turned into black …

Here are 2 results of which one is a compromise, we find colors of the original image.

I may be doing a filter to automate the process.
This is a first quick test.

The Gimp file with the commands in the layer names

test_transfert_palette.xcf.bz2 (4.0 MB)


Indeed, I messed up the PNG. I updated the post with palettes A and B. Thanks for taking the time to contribute.

(samj) #7

I will do tests with the 2 new pallets in the evening (Eastern time).


Sorry about the poor first answer, I ran out of time there. G’MIC in fact has so many ways of dealing with colour mapping I can hardly cover it all. CLUTs first:

gmic clut summer image.jpg map_clut. ..

That’s how to generate one of the pre-supplied cluts and apply it. Identity clut I’m not so sure about (there could be a command), but it’s not too hard to make one. Here’s one such method in a split up way you can play around with:

gmic 8,1,1,3,"int(x/(2^c))%2" r 2,2,2,3,-1 r 64,64,64,3,3 r 512,512,1,3,-1

Which is generate a starting clut, resize to a cube with no interpolation, resize to a larger cube with interpolation, resize to a 2d image for viewing.

A list of some commands you can use for colour mapping: index, map, warp, colormap, autoindex, quantize, patchmatch. Here’s an example with warp (I’m not declaring it looks great, it’s only for example!):

gmic pal.png colormap 5 r 4096,1,1,3,3 boats.jpg norm. n. 0,4096 warp.. .,0


(samj) #9

Here are the new tests with the 2 new pallets.

test_transfert_palette_v2.xcf.bz2 (4.0 MB)

(samj) #10

test_transfert_palette_v3.xcf.bz2 (4.0 MB)


The second one in your first post is really nice, as it doesn’t look posterised yet. It has a great balance between toned but still kinda real looking!

(samj) #12

Thank you.
To prevent posterization of the image, it is necessary to obtain a large number of colors from the original palette.
Gradients in CIE mode provide a large number of colors without intermediate colors out of range.
David Tschumperlé’s Transfer colors [advanced] filter provides results with many nuances :o)


I haven’t used resize in this way before. Much to learn. If you please, it would be nice to know how to go back and forth among the different representations. E.g., do and apply @Morgan_Hardwood’s approach #1 in gmic.


I’m never sure of the most efficient way, but here’s a possibility. First lets define two commands to make the example clearer:

#@cli hald
#@cli : Insert identity CLUT at the end of the image list.
hald: skip ${1=2}
  e. "Input identity CLUT with resolution $1."
  v - b={int($1)^2} s={$b^1.5}
  *. 255 r. $b,$b,$b,3,3 r. $s,$s,1,3,-1
  nm "[CLUT: identity]" v +

#@cli rle_values
#@cli : Reduce by repeating values removal.
  e. "Reduce image$? by repeating values removal." v -
  repeat $! -l[$>] r {w},1 f "i!=j(-1)?i:0;" s c discard 0 a c
  endl done nm "[RLE: values]" v +

The first is obviously to generate an identity clut of desired size. The second is to easily reduce the input image to single pixel values - we could of course create this by hand as above but I like the idea of making a command :slight_smile:
Now we can do this:

gmic pal2.png rle_values transpose hald 5 -r.. . norm. orientation.. -* boats.jpg map_clut. ..

whereby we turn the input colours into a 5 pixel vector, generate a clut, resize the palette and combine them (OK, I did cheat here using unit colour vectors and norm but the principal is similar). The last step is as above applying the clut to the image.

As an aside the resize command is very useful for interpolation and averaging. For example you can find the average r,g,b values of an image simply by resizing to 1x1x1x3 in average mode.


@samj Do the sizes of the gradients matter when you feed them to fx_transfer_rgb? I am guessing that the command only looks for unique colors…

(samj) #16

The result depends on the size of the color gradient.
I add a file with examples (xcf for Gimp 2.9.9).
test_transfert_palette_v4.xcf.bz2 (6.9 MB)


I know that length matters. What isn’t clear to me is whether width does too, or height as shown below. It doesn’t introduce more in-between colors as length does. From the v3 example:

I guess I could test it myself :slight_smile:.

(samj) #18

The width of the linear gradient will determine the number of colors. The height is not important.


@samj I tried samj_Palette_De_Degrades in CLI and got an error:

[gmic]./samj_Palette_De_Degrades/ *** Error *** Command ‘rv’: Invalid selection [-2,-1] (contains indice ‘-2’, not in range -1…0).

Also, I was wondering whether you could make it an arbitrary number of colours. I may have less than or more than 12. Thanks!

(G'MIC staff) #20

I’ve quickly tested a simple idea, let me explain it briefly.

Considering one source image I and one reference image R, we want to generate an image J that looks like I but with the colors of R.
What I’ve tried is :

  1. Take all the existing colors in R and put them in a CLUT. We end up with a volumetric image with a few colored points, and black everywhere else (so a lot of black).
  2. Use the G’MIC solidify algorithm (command solidify) on that sparse CLUT, to fill the missing values by interpolation the known colors of R (it uses diffusion PDEs for that task). -> Now, we have a full CLUT, with only interpolated colors from R.
  3. Apply that CLUT to the source image I to transfer the colors from R to I.

This is done basically by this code sample:

trcol :
  sp butterfly,dog  # Source and reference images
  64,64,64,4        # Resolution of the 3D CLUT : 64x64x64, with alpha-channel
  f.. "I(#-1,round(I/256*w#-1)) = [ I,255 ]"  # Fill CLUT with known colors of `R`.
  solidify. 75%,1,20  # CLUT completion -> all CLUT entries will get a color.
  +map_clut... .  # Apply that CLUT to the source image

I get something like this, for instance (Butterfly = source, Dog = reference) :

Another example (Pencils = source, Wall = reference) :

And another one (Greece = source, David = reference) :

Of course, if your reference image has a lot of different colors in it, there won’t be a lot of difference between the source image I and the generated image J.

Maybe this could be an idea for a new G’MIC filter in the plug-in, what do you think ?

Get the curves difference between 2 images like " Get Curves " Plugin does ?