Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine HSL variation to transform a color in another one

Tags:

colors

less

hsl

I use LESS, and I would like to take advantage by various integrated color functions that allow to set only few basic colors, and then derive others changing Hue, Saturation, Lightness, Spin, ecc.

Let's imagine that we have the following 2 colors (a light-green and a dark-green in this example) in my colorizer:

@primary-color:    rgb(0,100,60);
@secondary-color:  rgb(185,215,50); 

I would like to explicitly set only @primary-color and then obtain @secondary-color after an appropriate HSL transformation. (for example darken(hsl(90, 80%, 50%), 20%) )

Is there any way to determine what hsl setting I have to apply to @primary-color in order to gain @secondary-color?

In other words:

Given 2 RGB color definitions, is there any way to determine what difference in terms of Hue, Saturation and Lightness, exist between them, to express @secondary-color as a variations of @primary-color?

P.S.: maybe also with help of external tools like Photoshop, if necessary.

like image 892
Luca Detomi Avatar asked Dec 25 '22 22:12

Luca Detomi


1 Answers

Here is the way to calculate the difference between the hue, saturation and lightness values of two colors and then use it to calculate the second color based on the first.

The individual steps are as follows:

  • Color Difference Calculation: Calculate the Hue, Saturation and Lightness differences between the two given colors by using the hue(), saturation() and lightness() functions. This function can be used separately just to output the differences alone.
  • Arriving at the secondary color based on primary: This is a three step process and they are as follows:
    • Adjust the Hue of the primary color by using the spin() function by passing the hue difference between the two colors
    • Adjust the Saturation of the Hue Adjusted color (from previous step) by using the saturate() or desaturate() functions depending on the difference.
    • Adjust the Lightness of the Saturation Adjusted color (from previous step) by using the darken() or lighten() functions depending on the difference.

This answer is a Less adaptation of this SASS Article on how to calculate one color from another.

@primary: rgb(0,100,60); /* primary color */
@secondary: rgb(185,215,50); /* secondary color */

/* mixin to calculate the difference between two given colors */
.color-diff(@color1; @color2){ 
    @hueDiff: hue(@color2) - hue(@color1);
    @saturationDiff: saturation(@color1) - saturation(@color2);
    @lightnessDiff: lightness(@color1)- lightness(@color2);

    color1: @color1; color2:@color2; /* just for testing, can be removed */
}

/* Step 1: mixin to adjust the hue difference between the colors */
.adjust-hue(@color; @diff){ 
    @hueAdjusted: spin(@color, @hueDiff);
}

/* Step 2: mixin to adjust the saturation difference */
.adjust-saturation(@color; @diff) when (@diff > 0){
    @satAdjusted: desaturate(@color, abs(@diff)); /* desaturate if diff is greater than 0 */
}
.adjust-saturation(@color; @diff) when not (@diff > 0){
    @satAdjusted: saturate(@color, abs(@diff)); /* saturate if diff is not greater than 0 */
}

/* Step 3: mixin to adjust the lightness diff between the colors */
.adjust-lightness(@color; @diff) when (@diff > 0){
    @lightnessAdjusted: darken(@color, abs(@diff)); /* darken if diff is greater than 0 */
}
.adjust-lightness(@color; @diff) when not (@diff > 0){
    @lightnessAdjusted: lighten(@color, abs(@diff)); /* else lighten */
}

div{
    .color-diff(@primary; @secondary);
    .adjust-hue(@primary; @hueDiff);
    .adjust-saturation(@hueAdjusted; @saturationDiff);
    .adjust-lightness(@satAdjusted; @lightnessDiff);
    color: @lightnessAdjusted; /* final output value */
}

Compiled CSS:

div {
    color1: #00643c;
    color2: #b9d732;
    color: #b9d732;
}

If you would just wish to obtain the differences between two colors, then you could use a loop like below to output the differences in terms of hue, saturation and lightness values.

@color-list-1: rgb(0,100,60), #B0BCA7, #ABCDEF; /* list of primary colors */
@color-list-2: rgb(185,215,50), #BADA55, #FEDCBA; /* list of secondary colors */

#output{
    .loop-colors(@index) when (@index > 0){
        @primary: extract(@color-list-1, @index);
        @secondary: extract(@color-list-2, @index);
        .color-diff(@primary; @secondary);

        /* output the values of the comparison */
        color-comparison-@{index}+: ~"Hue Difference: @{hueDiff}";
        color-comparison-@{index}+: ~"Saturation Difference: @{saturationDiff}";        
        color-comparison-@{index}+: ~"Lightness Difference: @{lightnessDiff}";
        .loop-colors(@index - 1);
    }
    .loop-colors(length(@color-list-1));
}

The above code will compare the corresponding values in both lists and output their difference like below:

#output {
  color-comparison-3: Hue Difference: -180, Saturation Difference: -29.142857142857153%, Lightness Difference: -5.882352941176478%;
  color-comparison-2: Hue Difference: -19.849624060150404, Saturation Difference: -50.70282063269439%, Lightness Difference: 10.196078431372548%;
  color-comparison-1: Hue Difference: -85.09090909090908, Saturation Difference: 32.65306122448979%, Lightness Difference: -32.352941176470594%;
}
like image 152
Harry Avatar answered Jan 31 '23 00:01

Harry