﻿ How to Calculate Required Hue-Rotate to Generate Specific Colour - ITCodar

# How to Calculate Required Hue-Rotate to Generate Specific Colour

## How to calculate required hue-rotate to generate specific colour?

#### The only way to get the exact match is to use an SVG color matrix filter.

For RGB color #689d94, which is rgb(104, 157, 148), divide each primary color's value by 255:

$\frac{{\color{Red} 104}}{255}={\color{Red} 0.40784} ~~~~~~ \frac{{\color{DarkGreen} 157}}{255}={\color{DarkGreen} 0.61569} ~~~~~~ \frac{{\color{Blue} 148}}{255}={\color{Blue} 0.58039}$

Put these weights into the SVG <filter> matrix (5ᵗʰ column in the first 3 rows):

<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="689d94" color-interpolation-filters="sRGB">
<feColorMatrix type="matrix"
values="0 0 0 0 0.40784
0 0 0 0 0.61569
0 0 0 0 0.58039
0 0 0 1 0"/>
</filter>
</defs>
</svg>

The <filter> has to have id (I used the RGB hex code 689d94), so we can use it as a reference.

Since some browsers (e.g. Firefox) don't see/use the SVG filter if the display property of the SVG element is set to none, and having this SVG element in HTML code would inconveniently occupy some space, the best way is to convert this SVG into a pure inline CSS filter.

To get an inline filter value, take the above listed SVG code, transform it into a single line by remove line breaks and unnecessary spaces, then prepend url('data:image/svg+xml, and append the previously mentioned id as #689d94'):

div {
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="71.063" height="60.938"><path d="M33.938 0l-16.97 19.906H1.625L0 21.781v8.781l1.25 1.407h4.781l5.875 28.969h46.969l6.188-28.97h4.687l1.313-1.343v-8.844L69.5 19.906H54.656L37.312 0h-3.375zm1.593 7.594l9.594 12.312H26.25l9.281-12.312zm-20.281 16s-.405 2.9 1.594 3.844c1.998.942 4.406.03 4.406.03-1.666 2.763-3.638 3.551-5.469 2.688-3.312-1.562-.531-6.562-.531-6.562zm41.188.031s2.749 4.969-.563 6.531c-2.487 1.162-4.848-1.541-5.438-2.656 0 0 2.377.88 4.375-.063 1.999-.942 1.625-3.812 1.625-3.812z"/></svg>') no-repeat; // optimized from http://richard.parnaby-king.co.uk/basket.svg
background-size: 100%;
display: inline-block;
height: 5em;
width: 5em;
}
#colored {
filter: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"><defs><filter id="689d94" color-interpolation-filters="sRGB"><feColorMatrix type="matrix" values="0 0 0 0 0.40784 0 0 0 0 0.61569 0 0 0 0 0.58039 0 0 0 1 0"/></filter></defs></svg>#689d94');
margin-left: 20px;
}
<!-- No <svg> in HTML; pure CSS -->
<div></div><div id="colored"></div>
<p style="background: #689d94">​</p>

## Why is hue-rotate(180deg) not its own inverse?

hue-rotate(X) hue-rotate(X) is not equivalent to hue-rotate(X+X) as shown below:

.square {
height: 3rem;
background: linear-gradient( 90deg, rgba(255, 0, 0, 1) 0%, rgba(255, 154, 0, 1) 10%, rgba(208, 222, 33, 1) 20%, rgba(79, 220, 74, 1) 30%, rgba(63, 218, 216, 1) 40%, rgba(47, 201, 226, 1) 50%, rgba(28, 127, 238, 1) 60%, rgba(95, 21, 242, 1) 70%, rgba(186, 12, 248, 1) 80%, rgba(251, 7, 217, 1) 90%, rgba(255, 0, 0, 1) 100%);
font-family: monospace;
font-weight: bold;
color: white;
}

.single-invert {
filter: hue-rotate(360deg);
}

.double-invert {
filter: hue-rotate(180deg) hue-rotate(180deg);
}
<div class="square">filter: none</div>
<div class="square single-invert">filter: hue-rotate(360deg) </div>
<div class="square double-invert">filter: hue-rotate(180deg) hue-rotate(180deg)</div>

## Shift hue of an RGB Color

Edit per comment changed "are all" to "can be linearly approximated by".

Essentially, the steps you want are

RBG->HSV->Update hue->RGB

Since these can be approximated by linear matrix transforms (i.e. they are associative), you can perform it in a single step without any nasty conversion or loss of precision. You just multiple the transform matrices with each other, and use that to transform your colors.

There's a quick step by step here http://beesbuzz.biz/code/hsv_color_transforms.php

Here's the C++ code (With the saturation and value transforms removed):

Color TransformH(
const Color &in, // color to transform
float H
)
{
float U = cos(H*M_PI/180);
float W = sin(H*M_PI/180);

Color ret;
ret.r = (.299+.701*U+.168*W)*in.r
+ (.587-.587*U+.330*W)*in.g
+ (.114-.114*U-.497*W)*in.b;
ret.g = (.299-.299*U-.328*W)*in.r
+ (.587+.413*U+.035*W)*in.g
+ (.114-.114*U+.292*W)*in.b;
ret.b = (.299-.3*U+1.25*W)*in.r
+ (.587-.588*U-1.05*W)*in.g
+ (.114+.886*U-.203*W)*in.b;
return ret;
}