Log in

View Full Version : SelectiveColour v2.0 - an updated clone of Photoshop's Selective color adjustment


wonkey_monkey
4th March 2024, 21:20
SelectiveColour v2.0.1 (https://horman.net/avisynth/)
Direct download (https://horman.net/avisynth/download/SelectiveColour2.zip)


2.0.1: Incorporating threadpool fixes identified by pinterf in FastBlur


I've rewritten my old SelectiveColour filter (link to previous discussion (https://forum.doom9.org/showthread.php?t=151259)) using AVX instructions and now working exclusively in floating point RGB, so it's both faster and more accurate.

Also because I'm quite lazy, input clip width must be mod 8.

It's a clone of Photoshop's Selective color (https://helpx.adobe.com/photoshop/using/mix-colors.html) adjustment.

Apart from an input clip (which must be floating point planar RGB) it takes 19 required arguments, plus one optional argument.

The first 18 are floats in the range -1 to 1 (other values are accepted, but that behaviour is not well defined). These are in groups of three, representing the Cyan, Magenta, and Yellow percentages (normalised) present in Photoshop's Selective Color dialogue for each of the six colour sections (reds, yellows, greens, cyans, blues, magentas).

The 19th argument is a boolean to choose either relative (false) or absolute (true) mode, as per the Photoshop dialogue box.

The final optional named argument is "threads". This defaults to 1, but can be set to a higher number to enable multithreading. Two threads gave me a 25% speed increase, but not much more beyond that.

Usage:

...
ConvertBits(32)
ConvertToPlanarRGB
SelectiveColour(last,\
0.5,0,0,\
0.25,0.1,0,\
1,-0.5,-0.25,\
-0.5,0.5,-0.5,\
0.1,0.2,0.3,\
-0.1,-0.2,-0.3,\
true, threads = 2)


The six triples act on the following sets of pixels (any pixel may be a member of up to 2 adjacent sets):

Reds: those pixels where R>(G and B)
Yellows: (R and G)>B
Greens: G>(R and B)
Cyans: (G and B)>R
Blues: B>(R and G)
Magentas: (R and B)>G

The first number in a triple alters the Red channel, the second the Green channel, the third the Blue channel. Because Photoshop calls these values Cyan, Magenta and Yellow, the numbers work backwards - if you want to increase the intensity of a channel, use a negative number, and vice versa.

The filter still doesn't currently implement the "Black" value in Photoshop.

real.finder
6th April 2026, 09:14
no source code?

wonkey_monkey
6th April 2026, 14:27
Updated to 2.0.1 to incorporate threadpool fixes, and source code now included.

https://horman.net/avisynth/download/SelectiveColour2.zip

real.finder
7th April 2026, 00:30
Updated to 2.0.1 to incorporate threadpool fixes, and source code now included.

https://horman.net/avisynth/download/SelectiveColour2.zip

that was fast :eek:

thank you so much for releasing the source code

gispos
9th April 2026, 15:02
I have written a 'warpper' function for use in AvsPmod. Well suited for a preview filter. Maybe someone will like it.
If there are better suggestions for the parameter names, please change them.
Usage:

ConvertToPlanarRGB(bits=32)
/**avsp_filter
SelectiveColourW(RedA=0.00, RedB=0.00, RedC=0.00, YellowA=0.00, YellowB=0.00, YellowC=0.00, GreenA=0.00, GreenB=0.00, GreenC=0.00, \
CyanA=0.00, CyanB=0.00, CyanC=0.00, BlueA=0.00, BlueB=0.00, BlueC=0.00, MagentaA=0.00, MagentaB=0.00, MagentaC=0.00, relative=true, threads=2)
**/


The function itself, save it to an avs or avsi:

function SelectiveColourW(Clip clp, float "RedA",float "RedB",float "RedC", float "YellowA",float "YellowB",float "YellowC",\
float "GreenA",float "GreenB",float "GreenC", float "CyanA", float "CyanB", float "CyanC", float "BlueA", float "BlueB", float "BlueC", \
float "MagentaA", float "MagentaB", float "MagentaC", bool "relative", int "threads"){
clp
Assert((BitsPerComponent()==32) && IsPlanarRGB(), "Clip must be 32bit planar rgb")
rA=default(RedA, 0.00)
rB=default(RedB, 0.00)
rC=default(RedC, 0.00)
yA=default(YellowA, 0.00)
yB=default(YellowB, 0.00)
yC=default(YellowC, 0.00)
gA=default(GreenA, 0.00)
gB=default(GreenB, 0.00)
gC=default(GreenC, 0.00)
cA=default(CyanA, 0.00)
cB=default(CyanB, 0.00)
cC=default(CyanC, 0.00)
bA=default(BlueA, 0.00)
bB=default(BlueB, 0.00)
bC=default(BlueC, 0.00)
mA=default(MagentaA, 0.00)
mB=default(MagentaB, 0.00)
mC=default(MagentaC, 0.00)
rel=default(relative, True)
th=default(threads, 1)
SelectiveColour(rA,rB,rC,yA,yB,yC,gA,gB,gC,cA,cB,cC,bA,bB,bC,mA,mB,mC,rel,th)
}


For the AvsPmod sliders, the file filterdb.dat must be opened and now search for [USERFUNCTIONS] and copy it in after [USERFUNCTIONS].

[USERFUNCTIONS] # after that

SelectiveColourW(
clip,
float "RedA"=0.00 (-1.00 to 1.00),
float "RedB"=0.00 (-1.00 to 1.00),
float "RedC"=0.00 (-1.00 to 1.00),
float "YellowA"=0.00 (-1.00 to 1.00),
float "YellowB"=0.00 (-1.00 to 1.00),
float "YellowC"=0.00 (-1.00 to 1.00),
float "GreenA"=0.00 (-1.00 to 1.00),
float "GreenB"=0.00 (-1.00 to 1.00),
float "GreenC"=0.00 (-1.00 to 1.00),
float "CyanA"=0.00 (-1.00 to 1.00),
float "CyanB"=0.00 (-1.00 to 1.00),
float "CyanC"=0.00 (-1.00 to 1.00),
float "BlueA"=0.00 (-1.00 to 1.00),
float "BlueB"=0.00 (-1.00 to 1.00),
float "BlueC"=0.00 (-1.00 to 1.00),
float "MagentaA"=0.00 (-1.00 to 1.00),
float "MagentaB"=0.00 (-1.00 to 1.00),
float "MagentaC"=0.00 (-1.00 to 1.00),
bool "relative"=true,
int "threads"=1 (1 / 2 / 3 / 4)
)


Another method for the AvsPmod slider (no need to open filterdb.dat)
Goto Options > 'Avisynth functions definition...'
Select 'User functions'
Search for 'SelectiveColourW' and double click
In the Arguments field, write:

(clip,
float "RedA"=0.00 (-1.00 to 1.00),
float "RedB"=0.00 (-1.00 to 1.00),
float "RedC"=0.00 (-1.00 to 1.00),
float "YellowA"=0.00 (-1.00 to 1.00),
float "YellowB"=0.00 (-1.00 to 1.00),
float "YellowC"=0.00 (-1.00 to 1.00),
float "GreenA"=0.00 (-1.00 to 1.00),
float "GreenB"=0.00 (-1.00 to 1.00),
float "GreenC"=0.00 (-1.00 to 1.00),
float "CyanA"=0.00 (-1.00 to 1.00),
float "CyanB"=0.00 (-1.00 to 1.00),
float "CyanC"=0.00 (-1.00 to 1.00),
float "BlueA"=0.00 (-1.00 to 1.00),
float "BlueB"=0.00 (-1.00 to 1.00),
float "BlueC"=0.00 (-1.00 to 1.00),
float "MagentaA"=0.00 (-1.00 to 1.00),
float "MagentaB"=0.00 (-1.00 to 1.00),
float "MagentaC"=0.00 (-1.00 to 1.00),
bool "relative"=true,
int "threads"=1 (1 / 2 / 3 / 4)
)

click OK