It is currently June 18th, 2024, 8:09 am

Automatic Complementary Colors

Tips and Tricks from the Rainmeter Community
RicardoTM
Posts: 290
Joined: December 28th, 2022, 9:30 pm
Location: México

Automatic Complementary Colors

Post by RicardoTM »

Automatic Complementary Colors
HSL formulas were researched by Yincognito and I

Today I'd like to share 2 methods to obtain Complementary Colors from any given RGB code with only one measure, no lua required. At the end you'll find an Example Skin.

First things first.

What's a Complementary Color?

A Complementary Color is a color opposite to another color. When combined, cancel each other out to produce a grayscale color. You see complementary colors all the time, take a look at the Rainmeter Logo, it is using Teal and its complementary color, orange. Any brand or product we can think of uses complementary colors, every film you watch is graded using complementary colors (The most famous teal and orange aka "cinematic look"). Even in Nature. You can find complementary colors on different kinds of flowers, or even in the sunset and the ocean. These colors look good together, they are used for various purposes in art, design, and visual communication because they create contrast and enhance each other's intensity when placed side by side. They can make elements stand out, create dynamic compositions, and evoke certain moods or emotions in viewers. So there might be a chance you want to use these colors on your skin, so let's dive into it.

RGB Method

It's important to note that this method is not accurate, it messes with both saturation and luminance (A "true" complementary color preserves both luminance and saturation). Which makes it actually pretty good to create a bright text color against a dark background or vice versa.

ezgif.com-video-to-gif-converter.gif

Doing it is pretty easy, you only need to subtract 255 from each RGB value. Like this:

ComplementaryColor=(255-R),(255-G),(255-B)

You may think it is necessary to separate each RGB value before being able to compute the formula like this:

Code: Select all

;Splits 42,109,154 into R, G and B:
[R]
Group=Attributes
Measure=String
String=42,109,154
RegExpSubstitute=1
Substitute="^(\d+),(\d+),(\d+)$":"\1"
DynamicVariables=1

[G]
Group=Attributes
Measure=String
String=42,109,154
RegExpSubstitute=1
Substitute="^(\d+),(\d+),(\d+)$":"\2"
DynamicVariables=1

[B]
Group=Attributes
Measure=String
String=42,109,154
RegExpSubstitute=1
Substitute="^(\d+),(\d+),(\d+)$":"\3"
DynamicVariables=1
An then subtract 255 from each measure with another 3 measures and then use those results on the options and blah blah blah.

Not really, we can do everything in a single string measure by taking advantage of substitution and then letting the Color options do the math. Like this:

Code: Select all

[ComplementaryColor]
;This measure generates a complementary color.
Measure=String
String=42,109,154
RegExpSubstitute=1
Substitute="^(\d+),(\d+),(\d+)$":"(255-\1),(255-\2),(255-\3)"
DynamicVariables=1
This measure grabs the color "42,109,154" and delivers the string (255-42),(255-109),(255-154). And that's it, now we just use [ComplementaryColor] as a variable on any color option (DynamicVariables=1 required). Fortunately color options can do math. No extra calc measure needed. If you don't need to change the colors dynamically, then you can simply write the formula as is in the color option, no measure needed.

HSL Method

This method is the accurate one. It only shifts the hue while letting saturation and luminance intact. It's a little (ok, maybe a lot) more complicated, but it's as easy to use, this method doesn't work for any shade of grey (there's no hue on grey).

ezgif.com-video-to-gif-converter (1).gif
This method requires converting RGB colors to HSL and then back to RGB. Let's do it step by step first to understand the final one-measure implementation.

First we split the RGB values using substitutions:

Code: Select all

[R]
Measure=String
String=42,109,154
RegExpSubstitute=1
Substitute="^(\d+),(\d+),(\d+)$":"\1"
DynamicVariables=1

[G]
Measure=String
String=42,109,154
RegExpSubstitute=1
Substitute="^(\d+),(\d+),(\d+)$":"\2"
DynamicVariables=1

[B]
Measure=String
String=42,109,154
RegExpSubstitute=1
Substitute="^(\d+),(\d+),(\d+)$":"\3"
DynamicVariables=1
Then we calculate Hue, Saturation and Luminance using the appropriate formulas:

Code: Select all

[H]
Measure=Calc
Formula=(clamp((round(((Max(Max(([R]/255),([G]/255)),([B]/255))=Min(Min(([R]/255),([G]/255)),([B]/255)))?(0):(((Max(Max(([R]/255),([G]/255)),([B]/255))=([R]/255))?((6+(([G]/255)-([B]/255))/(Max(Max(([R]/255),([G]/255)),([B]/255))-Min(Min(([R]/255),([G]/255)),([B]/255))+0.000001))%6):((Max(Max(([R]/255),([G]/255)),([B]/255))=([G]/255))?((([B]/255)-([R]/255))/(Max(Max(([R]/255),([G]/255)),([B]/255))-Min(Min(([R]/255),([G]/255)),([B]/255))+0.000001)+2):((Max(Max(([R]/255),([G]/255)),([B]/255))=([B]/255))?((([R]/255)-([G]/255))/(Max(Max(([R]/255),([G]/255)),([B]/255))-Min(Min(([R]/255),([G]/255)),([B]/255))+0.000001)+4):(0))))*60)),3)),0,360))
DynamicVariables=1

[L]
Measure=Calc
Formula=(clamp((round(((Max(Max(([R]/255),([G]/255)),([B]/255))+Min(Min(([R]/255),([G]/255)),([B]/255)))/2),3)),0,1))
DynamicVariables=1

[S]
Measure=Calc
Formula=(clamp((round(((([L]=0)||([L]=1))?(0):((Max(Max(([R]/255),([G]/255)),([B]/255))-[L])/(Min([L],1-[L])+0.000001))),3)),0,1))
DynamicVariables=1
(If you want the formulas explained, ask Yincognito, he's better at diving into technicalities than me.)

Now we calculate the Complementary colors using the HSL to RGB formulas, but adding 180 "degrees" to the hue.

Code: Select all

[CR]
Measure=Calc
Formula=((Clamp(((round(([L]-[S]*Min([L],1-[L])*Max(-1,Min(Min(((0+([H]+180)/30)%12)-3,9-((0+([H]+180)/30)%12)),1))),3))*255),0,255)))
DynamicVariables=1

[CG]
Measure=Calc
Formula=(Clamp(((round(([L]-[S]*Min([L],1-[L])*Max(-1,Min(Min(((8+([H]+180)/30)%12)-3,9-((8+([H]+180)/30)%12)),1))),3))*255),0,255))
DynamicVariables=1

[CB]
Measure=Calc
Formula=(Clamp(((round(([L]-[S]*Min([L],1-[L])*Max(-1,Min(Min(((4+([H]+180)/30)%12)-3,9-((4+([H]+180)/30)%12)),1))),3))*255),0,255))
DynamicVariables=1
And that's it, now you can use [CR],[CG],[CB] on any color option.

As you can see there are a lot of steps we need to take to be able to obtain true complementary colors, fortunately we can just do all that in an single measure using the same trick we used on the RGB method with substitution:

Code: Select all

[ComplementaryColor]
;This measure generates a complementary color.
Measure=String
String=42,109,154
RegExpSubstitute=1
Substitute="^(\d+),(\d+),(\d+)$":"((Clamp(((round(((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))-(clamp((round(((((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))=0)||((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))=1))?(0):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))/(Min((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)),1-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))+0.000001))),3)),0,1))*Min((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)),1-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))*Max(-1,Min(Min(((0+((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=Min(Min(((\1)/255),((\2)/255)),((\3)/255)))?(0):(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\1)/255))?((6+(((\2)/255)-((\3)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001))%6):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\2)/255))?((((\3)/255)-((\1)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+2):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\3)/255))?((((\1)/255)-((\2)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+4):(0))))*60)),3)),0,360))+180)/30)%12)-3,9-((0+((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=Min(Min(((\1)/255),((\2)/255)),((\3)/255)))?(0):(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\1)/255))?((6+(((\2)/255)-((\3)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001))%6):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\2)/255))?((((\3)/255)-((\1)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+2):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\3)/255))?((((\1)/255)-((\2)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+4):(0))))*60)),3)),0,360))+180)/30)%12)),1))),3))*255),0,255))),(Clamp(((round(((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))-(clamp((round(((((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))=0)||((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))=1))?(0):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))/(Min((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)),1-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))+0.000001))),3)),0,1))*Min((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)),1-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))*Max(-1,Min(Min(((8+((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=Min(Min(((\1)/255),((\2)/255)),((\3)/255)))?(0):(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\1)/255))?((6+(((\2)/255)-((\3)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001))%6):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\2)/255))?((((\3)/255)-((\1)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+2):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\3)/255))?((((\1)/255)-((\2)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+4):(0))))*60)),3)),0,360))+180)/30)%12)-3,9-((8+((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=Min(Min(((\1)/255),((\2)/255)),((\3)/255)))?(0):(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\1)/255))?((6+(((\2)/255)-((\3)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001))%6):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\2)/255))?((((\3)/255)-((\1)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+2):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\3)/255))?((((\1)/255)-((\2)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+4):(0))))*60)),3)),0,360))+180)/30)%12)),1))),3))*255),0,255)),(Clamp(((round(((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))-(clamp((round(((((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))=0)||((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))=1))?(0):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))/(Min((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)),1-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))+0.000001))),3)),0,1))*Min((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)),1-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))*Max(-1,Min(Min(((4+((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=Min(Min(((\1)/255),((\2)/255)),((\3)/255)))?(0):(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\1)/255))?((6+(((\2)/255)-((\3)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001))%6):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\2)/255))?((((\3)/255)-((\1)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+2):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\3)/255))?((((\1)/255)-((\2)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+4):(0))))*60)),3)),0,360))+180)/30)%12)-3,9-((4+((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=Min(Min(((\1)/255),((\2)/255)),((\3)/255)))?(0):(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\1)/255))?((6+(((\2)/255)-((\3)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001))%6):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\2)/255))?((((\3)/255)-((\1)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+2):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\3)/255))?((((\1)/255)-((\2)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+4):(0))))*60)),3)),0,360))+180)/30)%12)),1))),3))*255),0,255))"
DynamicVariables=1
Yep, that's a 7,498 character single liner formula. It grabs the RGB color, splits it, converts it to HSL, adds 180 to the Hue and finally merges it back. Now you can simply use [ComplementaryColor] on any color option and let that meter compute the formula (DynamicVariables=1 required).

That's it, with this 2 methods you can generate complementary colors instantly. Here's an Example skin that also explains both methods. It also includes a fully functional Complementary Color Finder that uses the HSL method to create a split complementary color scheme, feeding it with only one color.
Captura de pantalla 2024-03-05 133333.jpg
Package:
ComplementaryColorsExample_1.2.rmskin
HSLiders recommended to use along with this example skin.

Changelog
1.2 Version: Now the example skin uses a split complementary scheme.
You do not have the required permissions to view the files attached to this post.
Last edited by RicardoTM on March 5th, 2024, 9:13 pm, edited 2 times in total.
RicardoTM
Posts: 290
Joined: December 28th, 2022, 9:30 pm
Location: México

Update: Automatic Complementary Colors

Post by RicardoTM »

Update

Example Skin no longer uses RGB method, it now uses only HSL method to generate a Double Split Complementary color scheme that is applied to the background and text color automatically.
ezgif.com-video-to-gif-converter (2).gif
You do not have the required permissions to view the files attached to this post.
User avatar
balala
Rainmeter Sage
Posts: 16310
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Automatic Complementary Colors

Post by balala »

Interesting procedure, especially the HSL one. Quite long substitution, but definitely works. Congratulations and thanks. :great:
RicardoTM
Posts: 290
Joined: December 28th, 2022, 9:30 pm
Location: México

Re: Automatic Complementary Colors

Post by RicardoTM »

balala wrote: March 6th, 2024, 7:24 pm Interesting procedure, especially the HSL one. Quite long substitution, but definitely works. Congratulations and thanks. :great:
It is, you can also use it to shift hue at will by replacing the +180 for a variable like #Angle#, then you can shift it to whatever you want:

Code: Select all

[Variables]
Color=68,50,255
Angle=180

[HueShift]
;This measure shifts a color hue by a given angle.
Measure=String
String=[#Color]
RegExpSubstitute=1
Substitute="^(\d+),(\d+),(\d+)$":"((Clamp(((round(((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))-(clamp((round(((((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))=0)||((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))=1))?(0):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))/(Min((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)),1-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))+0.000001))),3)),0,1))*Min((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)),1-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))*Max(-1,Min(Min(((0+((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=Min(Min(((\1)/255),((\2)/255)),((\3)/255)))?(0):(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\1)/255))?((6+(((\2)/255)-((\3)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001))%6):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\2)/255))?((((\3)/255)-((\1)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+2):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\3)/255))?((((\1)/255)-((\2)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+4):(0))))*60)),3)),0,360))+([#Angle]))/30)%12)-3,9-((0+((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=Min(Min(((\1)/255),((\2)/255)),((\3)/255)))?(0):(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\1)/255))?((6+(((\2)/255)-((\3)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001))%6):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\2)/255))?((((\3)/255)-((\1)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+2):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\3)/255))?((((\1)/255)-((\2)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+4):(0))))*60)),3)),0,360))+([#Angle]))/30)%12)),1))),3))*255),0,255))),(Clamp(((round(((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))-(clamp((round(((((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))=0)||((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))=1))?(0):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))/(Min((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)),1-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))+0.000001))),3)),0,1))*Min((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)),1-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))*Max(-1,Min(Min(((8+((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=Min(Min(((\1)/255),((\2)/255)),((\3)/255)))?(0):(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\1)/255))?((6+(((\2)/255)-((\3)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001))%6):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\2)/255))?((((\3)/255)-((\1)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+2):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\3)/255))?((((\1)/255)-((\2)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+4):(0))))*60)),3)),0,360))+([#Angle]))/30)%12)-3,9-((8+((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=Min(Min(((\1)/255),((\2)/255)),((\3)/255)))?(0):(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\1)/255))?((6+(((\2)/255)-((\3)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001))%6):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\2)/255))?((((\3)/255)-((\1)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+2):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\3)/255))?((((\1)/255)-((\2)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+4):(0))))*60)),3)),0,360))+([#Angle]))/30)%12)),1))),3))*255),0,255)),(Clamp(((round(((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))-(clamp((round(((((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))=0)||((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1))=1))?(0):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))/(Min((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)),1-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))+0.000001))),3)),0,1))*Min((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)),1-(clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))+Min(Min(((\1)/255),((\2)/255)),((\3)/255)))/2),3)),0,1)))*Max(-1,Min(Min(((4+((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=Min(Min(((\1)/255),((\2)/255)),((\3)/255)))?(0):(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\1)/255))?((6+(((\2)/255)-((\3)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001))%6):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\2)/255))?((((\3)/255)-((\1)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+2):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\3)/255))?((((\1)/255)-((\2)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+4):(0))))*60)),3)),0,360))+([#Angle]))/30)%12)-3,9-((4+((clamp((round(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=Min(Min(((\1)/255),((\2)/255)),((\3)/255)))?(0):(((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\1)/255))?((6+(((\2)/255)-((\3)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001))%6):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\2)/255))?((((\3)/255)-((\1)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+2):((Max(Max(((\1)/255),((\2)/255)),((\3)/255))=((\3)/255))?((((\1)/255)-((\2)/255))/(Max(Max(((\1)/255),((\2)/255)),((\3)/255))-Min(Min(((\1)/255),((\2)/255)),((\3)/255))+0.000001)+4):(0))))*60)),3)),0,360))+([#Angle]))/30)%12)),1))),3))*255),0,255))"
DynamicVariables=1

User avatar
balala
Rainmeter Sage
Posts: 16310
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Automatic Complementary Colors

Post by balala »

RicardoTM wrote: March 6th, 2024, 7:53 pm It is, you can also use it to shift hue at will by replacing the +180 for a variable like #Angle#, then you can shift it to whatever you want:
:thumbup: